laravel-echo-api-gateway 0.5.8 → 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.js CHANGED
@@ -12,5 +12,6 @@ module.exports = {
12
12
  "@typescript-eslint/ban-types": "off",
13
13
  "@typescript-eslint/no-explicit-any": "off",
14
14
  "prefer-const": "off",
15
+ "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
15
16
  },
16
17
  };
@@ -8,10 +8,25 @@ jobs:
8
8
  pest:
9
9
  runs-on: ubuntu-latest
10
10
  strategy:
11
- fail-fast: true
11
+ fail-fast: false
12
12
  matrix:
13
- php: ['8.1']
14
- name: Pest - PHP ${{ matrix.php }}
13
+ include:
14
+ - php: '8.1'
15
+ laravel: '^10.0'
16
+ testbench: '^8.0'
17
+ - php: '8.2'
18
+ laravel: '^11.0'
19
+ testbench: '^9.0'
20
+ - php: '8.3'
21
+ laravel: '^12.0'
22
+ testbench: '^10.0'
23
+ - php: '8.4'
24
+ laravel: '^12.0'
25
+ testbench: '^10.0'
26
+ - php: '8.5'
27
+ laravel: '^13.0'
28
+ testbench: '^11.0'
29
+ name: Pest - PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
15
30
  steps:
16
31
  - uses: actions/checkout@v4
17
32
  - uses: shivammathur/setup-php@v2
@@ -19,35 +34,35 @@ jobs:
19
34
  php-version: ${{ matrix.php }}
20
35
  extensions: dom, mbstring, soap, bcmath, pdo_sqlite, intl
21
36
  coverage: pcov
22
- - uses: ramsey/composer-install@v1
23
- with:
24
- composer-options: "--prefer-dist --optimize-autoloader --ignore-platform-reqs"
37
+ - name: Install dependencies
38
+ run: |
39
+ composer update --no-interaction --prefer-dist --with-all-dependencies \
40
+ --with "laravel/framework:${{ matrix.laravel }}" \
41
+ --with "orchestra/testbench:${{ matrix.testbench }}"
25
42
  - name: Run PestPHP
26
- run: vendor/bin/pest --coverage --coverage-clover test-results/pest.xml
43
+ run: vendor/bin/pest --coverage-clover test-results/pest.xml
27
44
  env:
28
45
  AWS_ACCESS_KEY_ID: fake
29
46
  AWS_SECRET_ACCESS_KEY: fake
30
47
  AWS_SESSION_TOKEN: fake
31
48
  - name: Upload coverage to Codecov
32
49
  if: always()
33
- uses: codecov/codecov-action@v2
50
+ uses: codecov/codecov-action@v4
34
51
  with:
35
52
  token: ${{ secrets.CODECOV_TOKEN }}
36
53
  flags: pest-${{ matrix.php }}
37
- file: test-results/pest.xml
54
+ files: test-results/pest.xml
38
55
 
39
56
  larastan:
40
57
  runs-on: ubuntu-latest
41
58
  name: Larastan
42
59
  steps:
43
- - uses: actions/checkout@v2
60
+ - uses: actions/checkout@v4
44
61
  - uses: shivammathur/setup-php@v2
45
62
  with:
46
- php-version: ${{ matrix.php }}
63
+ php-version: '8.4'
47
64
  extensions: soap, bcmath, pdo_sqlite, intl
48
- - uses: ramsey/composer-install@v1
49
- with:
50
- composer-options: "--prefer-dist --optimize-autoloader --ignore-platform-reqs"
65
+ - uses: ramsey/composer-install@v3
51
66
  - name: Run Larastan
52
67
  run: vendor/bin/phpstan analyse --no-progress
53
68
 
@@ -55,49 +70,38 @@ jobs:
55
70
  runs-on: ubuntu-latest
56
71
  name: ESLint
57
72
  steps:
58
- - uses: actions/checkout@v2
73
+ - uses: actions/checkout@v4
74
+ - uses: actions/setup-node@v4
75
+ with:
76
+ node-version: '22'
59
77
  - name: Install dependencies
60
- run: npm install
78
+ run: npm ci
61
79
  - name: Run ESLint
62
80
  run: npm run lint
63
81
 
64
82
  jest:
65
83
  runs-on: ubuntu-latest
66
- name: Jest
84
+ strategy:
85
+ fail-fast: false
86
+ matrix:
87
+ node: ['18', '20', '22']
88
+ # The suite runs every test against laravel-echo v1 (aliased as laravel-echo-v1) and v2.
89
+ name: Jest - Node ${{ matrix.node }}
67
90
  steps:
68
- - uses: actions/checkout@v2
69
- - uses: actions/setup-node@v2
91
+ - uses: actions/checkout@v4
92
+ - uses: actions/setup-node@v4
70
93
  with:
71
- node-version: '15'
94
+ node-version: ${{ matrix.node }}
72
95
  - name: Install dependencies
73
- run: npm install
96
+ run: npm ci
97
+ - name: Build
98
+ run: npm run build
74
99
  - name: Run Jest
75
- run: npm run test --coverage --coverageDirectory=test-results/jest
100
+ run: npm test -- --coverage --coverageDirectory=test-results/jest
76
101
  - name: Upload coverage to Codecov
77
102
  if: always()
78
- uses: codecov/codecov-action@v1
103
+ uses: codecov/codecov-action@v4
79
104
  with:
80
105
  token: ${{ secrets.CODECOV_TOKEN }}
81
106
  flags: jest
82
- file: test-results/jest/clover.xml
83
- # phpcs:
84
- # runs-on: ubuntu-latest
85
- # name: PHP Style Fixer
86
- # steps:
87
- # - uses: actions/checkout@v2
88
- # - uses: shivammathur/setup-php@v2
89
- # with:
90
- # php-version: '7.4'
91
- # extensions: soap, bcmath, pdo_sqlite
92
- # - name: Get Composer Cache Directory
93
- # id: composer-cache
94
- # run: echo "::set-output name=dir::$(composer config cache-files-dir)"
95
- # - uses: actions/cache@v2
96
- # with:
97
- # path: ${{ steps.composer-cache.outputs.dir }}
98
- # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
99
- # restore-keys: ${{ runner.os }}-composer-
100
- # - name: Install Composer dependencies
101
- # run: composer install --no-interaction --no-progress --prefer-dist --optimize-autoloader --ignore-platform-reqs
102
- # - name: Run PHP-CS-Fixer
103
- # run: vendor/bin/php-cs-fixer fix --dry-run --diff --allow-risky=yes
107
+ files: test-results/jest/clover.xml
package/README.md CHANGED
@@ -18,10 +18,11 @@ though the latter one involves some manual set-up.
18
18
  In order to use this package, your project needs to meet the following criteria:
19
19
 
20
20
  - PHP 8.x
21
- - Laravel 6 to 12
21
+ - Laravel 6 to 13
22
22
  - Uses either [bref](https://bref.sh) or [Laravel Vapor](https://vapor.laravel.com) to deploy to AWS
23
23
  - Has a working queue
24
- - Uses Laravel Mix or any other tool to bundle your assets
24
+ - Uses [laravel-echo](https://github.com/laravel/echo) v1.10+ or v2 on the client
25
+ - Uses Vite, Laravel Mix or any other tool to bundle your assets (or Node.js 18+ for non-browser clients)
25
26
 
26
27
  ## Installation
27
28
 
@@ -32,11 +33,11 @@ First we have to install both the composer and npm package:
32
33
  ```shell
33
34
  composer require georgeboot/laravel-echo-api-gateway
34
35
 
35
- yarn add laravel-echo-api-gateway
36
- # or
37
- npm install --save-dev laravel-echo-api-gateway
36
+ npm install --save-dev laravel-echo laravel-echo-api-gateway
38
37
  ```
39
38
 
39
+ `laravel-echo` is a peer dependency: the package works with the version your app already uses (v1.10+ or v2).
40
+
40
41
  ### Platform-specific instructions
41
42
 
42
43
  #### A. When using Bref
@@ -51,8 +52,7 @@ functions:
51
52
  # Add this function
52
53
  websocket:
53
54
  handler: handlers/websocket.php
54
- layers:
55
- - ${bref:layer.php-80}
55
+ runtime: php-83
56
56
  events:
57
57
  - websocket: $disconnect
58
58
  - websocket: $default
@@ -122,6 +122,8 @@ provider:
122
122
  LARAVEL_ECHO_API_GATEWAY_DYNAMODB_TABLE: !Ref ConnectionsTable
123
123
  LARAVEL_ECHO_API_GATEWAY_API_ID: !Ref WebsocketsApi
124
124
  LARAVEL_ECHO_API_GATEWAY_API_STAGE: "${self:provider.stage}"
125
+ # Optional, see "Signing secret" below
126
+ LARAVEL_ECHO_API_GATEWAY_SECRET: ${ssm:/my-app/echo-api-gateway-secret}
125
127
  ```
126
128
 
127
129
  Next, create the PHP handler file in `handlers/websocket.php`
@@ -180,38 +182,112 @@ BROADCAST_DRIVER=laravel-echo-api-gateway
180
182
  LARAVEL_ECHO_API_GATEWAY_DYNAMODB_TABLE=the-table-name-you-entered-when-creating-it
181
183
  LARAVEL_ECHO_API_GATEWAY_API_ID=your-websocket-api-id
182
184
  LARAVEL_ECHO_API_GATEWAY_API_STAGE=your-api-stage-name
185
+ # Optional, see "Signing secret" below
186
+ LARAVEL_ECHO_API_GATEWAY_SECRET=a-long-random-string
183
187
  ```
184
188
 
189
+ ### Signing secret
190
+
191
+ Private and presence channels are authorized by your app (`/broadcasting/auth`), which signs the socket id and channel
192
+ name. The websocket handler verifies that signature before subscribing the connection. By default both use your
193
+ `APP_KEY`. If the websocket handler runs as a separate app, set the same `LARAVEL_ECHO_API_GATEWAY_SECRET` on both
194
+ instead of sharing your `APP_KEY`.
195
+
185
196
  ### Generate front-end code
186
197
 
187
198
  Add to your javascript file:
188
199
 
189
200
  ```js
190
201
  import Echo from 'laravel-echo';
191
- import {broadcaster} from 'laravel-echo-api-gateway';
202
+ import { Connector } from 'laravel-echo-api-gateway';
192
203
 
193
204
  window.Echo = new Echo({
194
- broadcaster,
205
+ broadcaster: Connector,
195
206
  // replace the placeholders
196
- host: 'wss://{api-ip}.execute-api.{region}.amazonaws.com/{stage}',
207
+ host: 'wss://{api-id}.execute-api.{region}.amazonaws.com/{stage}',
197
208
  authEndpoint: '{auth-url}/broadcasting/auth', // Optional: Use if you have a separate authentication endpoint
198
209
  bearerToken: '{token}', // Optional: Use if you need a Bearer Token for authentication
199
210
  });
200
211
  ```
201
212
 
202
- You can also enable console output by passing a `debug: true` otpion to your window.Echo intializer :
213
+ The `broadcaster` export from previous versions keeps working: `new Echo({ broadcaster, ... })`.
214
+
215
+ With TypeScript and laravel-echo v2, its typings do not accept custom connector classes yet, so cast the option:
216
+ `broadcaster: Connector as any`.
217
+
218
+ #### Using `@laravel/echo-react` or `@laravel/echo-vue`
219
+
220
+ ```ts
221
+ import { configureEcho } from '@laravel/echo-react';
222
+ import { Connector } from 'laravel-echo-api-gateway';
223
+
224
+ configureEcho({
225
+ broadcaster: Connector as any,
226
+ host: import.meta.env.VITE_ECHO_API_GATEWAY_HOST,
227
+ });
228
+ ```
229
+
230
+ #### Using it outside the browser (Node.js, Electron)
231
+
232
+ The connector only needs the global `WebSocket` and `fetch`, available in Node.js 22+ (or 18+ with a `WebSocket`
233
+ polyfill such as [ws](https://github.com/websockets/ws) assigned to `globalThis.WebSocket`).
234
+
235
+ To authorize private channels with your own logic, pass a custom handler. It receives the socket id and channel name
236
+ and must call back with the response of your `/broadcasting/auth` endpoint:
237
+
203
238
  ```js
204
- import Echo from 'laravel-echo';
205
- import {broadcaster} from 'laravel-echo-api-gateway';
239
+ const echo = new Echo({
240
+ broadcaster: Connector,
241
+ host: 'wss://{api-id}.execute-api.{region}.amazonaws.com/{stage}',
242
+ channelAuthorization: {
243
+ customHandler: ({ socketId, channelName }, callback) => {
244
+ fetch('https://my-app.test/api/broadcasting/auth', {
245
+ method: 'POST',
246
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
247
+ body: JSON.stringify({ socket_id: socketId, channel_name: channelName }),
248
+ })
249
+ .then((response) => response.json())
250
+ .then((data) => callback(null, data))
251
+ .catch((error) => callback(error, null));
252
+ },
253
+ },
254
+ });
255
+ ```
256
+
257
+ You can also pass `channelAuthorization: { endpoint, headers }` to only change the endpoint or add headers.
258
+ Authorization failures and rejected subscriptions are reported to `channel.error(callback)`.
259
+
260
+ #### Options
206
261
 
262
+ | Option | Default | Description |
263
+ | --- | --- | --- |
264
+ | `host` | | The websocket URL of your API Gateway stage. |
265
+ | `authEndpoint` | `/broadcasting/auth` | Endpoint used to authorize private and presence channels. |
266
+ | `bearerToken` | | Sent as `Authorization: Bearer ...` to the auth endpoint. |
267
+ | `auth.headers` | `{}` | Extra headers sent to the auth endpoint. |
268
+ | `channelAuthorization` | | `{ endpoint, headers, customHandler }`, see above. |
269
+ | `pingInterval` | `60000` | Milliseconds between keep-alive pings. API Gateway closes idle connections after 10 minutes. |
270
+ | `reconnectDelay` | `1000` | Milliseconds before the first reconnect attempt. Later attempts back off exponentially. |
271
+ | `maxReconnectDelay` | `30000` | Upper bound for the reconnect delay. |
272
+ | `debug` | `false` | Log connection activity to the console. |
273
+
274
+ API Gateway closes every websocket connection after 2 hours. The connector reconnects automatically and subscribes
275
+ again to every channel you joined, so your listeners keep receiving events.
276
+
277
+ You can also enable console output by passing a `debug: true` option to your Echo initializer:
278
+
279
+ ```js
207
280
  window.Echo = new Echo({
208
- broadcaster,
209
- // replace the placeholders
210
- host: 'wss://{api-ip}.execute-api.{region}.amazonaws.com/{stage}',
281
+ broadcaster: Connector,
282
+ host: 'wss://{api-id}.execute-api.{region}.amazonaws.com/{stage}',
211
283
  debug: true
212
284
  });
213
285
  ```
214
286
 
287
+ Lastly, build your assets (for example with Vite or Laravel Mix). After this step, you should be up and running.
215
288
 
289
+ ### Limitations
216
290
 
217
- Lastly, you have to generate your assets by running Laravel Mix. After this step, you should be up and running.
291
+ - Presence channels can be joined, but member tracking (`here`, `joining`, `leaving`) is not implemented yet.
292
+ - Client events (whispers) can only be sent by connections subscribed to the private or presence channel, like Pusher.
293
+ - Encrypted private channels are not supported.
@@ -0,0 +1,89 @@
1
+ import { EventFormatter } from "./EventFormatter";
2
+ import { Websocket } from "./Websocket";
3
+ import type { Options } from "./Websocket";
4
+ /**
5
+ * A channel on the API Gateway websocket. It implements the public, private and presence channel
6
+ * interfaces of laravel-echo (v1 and v2) without extending its internal classes.
7
+ */
8
+ export declare class Channel {
9
+ /**
10
+ * The websocket connection.
11
+ */
12
+ socket: Websocket;
13
+ /**
14
+ * The name of the channel.
15
+ */
16
+ name: string;
17
+ /**
18
+ * Channel options.
19
+ */
20
+ options: Options;
21
+ /**
22
+ * The event formatter.
23
+ */
24
+ eventFormatter: EventFormatter;
25
+ /**
26
+ * Create a new class instance.
27
+ */
28
+ constructor(socket: Websocket, name: string, options: Options);
29
+ /**
30
+ * Subscribe to the channel.
31
+ */
32
+ subscribe(): void;
33
+ /**
34
+ * Unsubscribe from the channel.
35
+ */
36
+ unsubscribe(): void;
37
+ /**
38
+ * Listen for an event on the channel instance.
39
+ */
40
+ listen(event: string, callback: Function): this;
41
+ /**
42
+ * Stop listening for an event on the channel instance. Without a callback, every listener of the event is removed.
43
+ */
44
+ stopListening(event: string, callback?: Function): this;
45
+ /**
46
+ * Listen for a whisper event on the channel instance.
47
+ */
48
+ listenForWhisper(event: string, callback: Function): this;
49
+ /**
50
+ * Stop listening for a whisper event on the channel instance.
51
+ */
52
+ stopListeningForWhisper(event: string, callback?: Function): this;
53
+ /**
54
+ * Listen for an event on the channel instance.
55
+ */
56
+ notification(callback: Function): this;
57
+ /**
58
+ * Stop listening for notification events on the channel instance.
59
+ */
60
+ stopListeningForNotification(callback?: Function): this;
61
+ /**
62
+ * Register a callback to be called anytime a subscription succeeds.
63
+ */
64
+ subscribed(callback: Function): this;
65
+ /**
66
+ * Register a callback to be called anytime a subscription or authorization error occurs.
67
+ */
68
+ error(callback: Function): this;
69
+ /**
70
+ * Bind a channel to an event.
71
+ */
72
+ on(event: string, callback: Function): this;
73
+ /**
74
+ * Send a client event to the other members of the channel.
75
+ */
76
+ whisper(event: string, data: unknown): this;
77
+ /**
78
+ * Presence channels are not supported yet: member tracking is not implemented on the server.
79
+ */
80
+ here(_callback: Function): this;
81
+ /**
82
+ * Presence channels are not supported yet: member tracking is not implemented on the server.
83
+ */
84
+ joining(_callback: Function): this;
85
+ /**
86
+ * Presence channels are not supported yet: member tracking is not implemented on the server.
87
+ */
88
+ leaving(_callback: Function): this;
89
+ }
@@ -0,0 +1,92 @@
1
+ import { Websocket } from "./Websocket";
2
+ import type { Options } from "./Websocket";
3
+ import { Channel } from "./Channel";
4
+ export { Channel };
5
+ export { EventFormatter } from "./EventFormatter";
6
+ export type { AuthorizationData, AuthorizationError, ChannelAuthorization, Options } from "./Websocket";
7
+ /**
8
+ * Laravel Echo connector for API Gateway websockets.
9
+ *
10
+ * It does not extend laravel-echo's internal classes, so it works with laravel-echo v1 and v2:
11
+ * both create custom connectors with `new options.broadcaster(options)`.
12
+ */
13
+ export declare class Connector {
14
+ /**
15
+ * Default connector options, matching laravel-echo's defaults.
16
+ */
17
+ static readonly _defaultOptions: {
18
+ auth: {
19
+ headers: {};
20
+ };
21
+ authEndpoint: string;
22
+ csrfToken: any;
23
+ bearerToken: any;
24
+ host: any;
25
+ namespace: string;
26
+ };
27
+ /**
28
+ * Connector options.
29
+ */
30
+ options: Options;
31
+ socket: Websocket;
32
+ /**
33
+ * All of the subscribed channel names.
34
+ */
35
+ channels: {
36
+ [name: string]: Channel;
37
+ };
38
+ /**
39
+ * Create a new class instance. Without a host no connection is opened, which keeps
40
+ * laravel-echo v2's `new broadcaster()` capability check free of side effects.
41
+ */
42
+ constructor(options?: Options);
43
+ /**
44
+ * Merge the custom options with the defaults and add the CSRF and bearer token headers.
45
+ */
46
+ protected setOptions(options: Options): void;
47
+ /**
48
+ * Extract the CSRF token from the page.
49
+ */
50
+ protected csrfToken(): string | null;
51
+ /**
52
+ * Create a fresh websocket connection.
53
+ */
54
+ connect(): void;
55
+ /**
56
+ * Listen for an event on a channel instance.
57
+ */
58
+ listen(name: string, event: string, callback: Function): Channel;
59
+ /**
60
+ * Get a channel instance by name.
61
+ */
62
+ channel(name: string): Channel;
63
+ /**
64
+ * Get a private channel instance by name.
65
+ */
66
+ privateChannel(name: string): Channel;
67
+ /**
68
+ * Get a presence channel instance by name.
69
+ */
70
+ presenceChannel(name: string): Channel;
71
+ /**
72
+ * Leave the given channel, as well as its private and presence variants.
73
+ */
74
+ leave(name: string): void;
75
+ /**
76
+ * Leave the given channel.
77
+ */
78
+ leaveChannel(name: string): void;
79
+ /**
80
+ * Get the socket ID for the connection.
81
+ */
82
+ socketId(): string | undefined;
83
+ /**
84
+ * Disconnect socket connection.
85
+ */
86
+ disconnect(): void;
87
+ }
88
+ /**
89
+ * Kept for backwards compatibility: `new Echo({ broadcaster })`. A function declaration (not an arrow
90
+ * function) so laravel-echo can call it with `new`.
91
+ */
92
+ export declare function broadcaster(options?: Options): Connector;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Formats event names the same way laravel-echo does, so `listen('OrderCreated')` matches
3
+ * `App\Events\OrderCreated` and `listen('.custom-name')` matches `custom-name`.
4
+ */
5
+ export declare class EventFormatter {
6
+ private namespace;
7
+ constructor(namespace: string | false);
8
+ format(event: string): string;
9
+ setNamespace(namespace: string | false): void;
10
+ }
@@ -0,0 +1,78 @@
1
+ import type { Channel } from "./Channel";
2
+ export type ChannelAuthorizationCallback = (error: unknown, data: AuthorizationData | null) => void;
3
+ export type ChannelAuthorization = {
4
+ endpoint?: string;
5
+ headers?: Record<string, string>;
6
+ customHandler?: (params: {
7
+ socketId: string;
8
+ channelName: string;
9
+ }, callback: ChannelAuthorizationCallback) => void;
10
+ };
11
+ export type Options = {
12
+ host?: string;
13
+ authEndpoint?: string;
14
+ auth?: {
15
+ headers: Record<string, string>;
16
+ };
17
+ channelAuthorization?: ChannelAuthorization;
18
+ bearerToken?: string | null;
19
+ csrfToken?: string | null;
20
+ namespace?: string | false;
21
+ debug?: boolean;
22
+ /** Milliseconds between keep-alive pings. API Gateway closes idle connections after 10 minutes. */
23
+ pingInterval?: number;
24
+ /** Milliseconds to wait before the first reconnect attempt. Later attempts back off exponentially. */
25
+ reconnectDelay?: number;
26
+ /** Upper bound for the reconnect delay, in milliseconds. */
27
+ maxReconnectDelay?: number;
28
+ [key: string]: any;
29
+ };
30
+ export type MessageBody = {
31
+ event: string;
32
+ channel?: string;
33
+ data?: any;
34
+ };
35
+ export type AuthorizationData = {
36
+ auth: string;
37
+ channel_data?: string;
38
+ };
39
+ export type AuthorizationError = {
40
+ type: 'AuthError';
41
+ status: number | null;
42
+ error: unknown;
43
+ };
44
+ export declare class Websocket {
45
+ options: Options;
46
+ websocket: WebSocket | undefined;
47
+ private buffer;
48
+ /**
49
+ * Every channel that should be subscribed, re-subscribed each time a new connection is identified.
50
+ */
51
+ private channels;
52
+ private listeners;
53
+ private socketId;
54
+ private closing;
55
+ private reconnectAttempts;
56
+ private reconnectTimer;
57
+ private pingTimer;
58
+ constructor(options: Options);
59
+ private connect;
60
+ private scheduleReconnect;
61
+ private startPing;
62
+ private stopPing;
63
+ private handleMessage;
64
+ private dispatch;
65
+ protected parseMessage(body: string): MessageBody | undefined;
66
+ getSocketId(): string | undefined;
67
+ private socketIsReady;
68
+ send(message: MessageBody): void;
69
+ close(): void;
70
+ subscribe(channel: Channel): void;
71
+ private actuallySubscribe;
72
+ private authorize;
73
+ private authorizationError;
74
+ unsubscribe(channel: Channel): void;
75
+ bind(channel: Channel, event: string, callback: Function): void;
76
+ unbind(channel: Channel, event: string, callback?: Function): void;
77
+ private debug;
78
+ }