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 +1 -0
- package/.github/workflows/ci.yml +49 -45
- package/README.md +93 -17
- package/dist/Channel.d.ts +89 -0
- package/dist/Connector.d.ts +92 -0
- package/dist/EventFormatter.d.ts +10 -0
- package/dist/Websocket.d.ts +78 -0
- package/dist/laravel-echo-api-gateway.common.js +403 -762
- package/dist/laravel-echo-api-gateway.iife.js +487 -846
- package/dist/laravel-echo-api-gateway.js +401 -760
- package/jest.config.js +3 -7
- package/js-src/Channel.ts +74 -62
- package/js-src/Connector.ts +100 -40
- package/js-src/EventFormatter.ts +24 -0
- package/js-src/Websocket.ts +217 -168
- package/js-tests/Connector.test.ts +295 -60
- package/js-tests/EchoCompatibility.test.ts +96 -0
- package/js-tests/helpers.ts +37 -0
- package/package.json +23 -30
- package/phpstan.neon.dist +3 -12
- package/phpunit.xml +2 -2
- package/rollup.config.mjs +14 -0
- package/tsconfig.json +6 -6
- package/dist/js-src/Channel.d.ts +0 -68
- package/dist/js-src/Connector.d.ts +0 -49
- package/dist/js-src/Websocket.d.ts +0 -38
- package/rollup.config.js +0 -31
|
@@ -1,880 +1,521 @@
|
|
|
1
1
|
var LaravelEchoApiGateway = (function (exports) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
function _createClass(Constructor, protoProps, staticProps) {
|
|
21
|
-
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
22
|
-
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
23
|
-
Object.defineProperty(Constructor, "prototype", {
|
|
24
|
-
writable: false
|
|
25
|
-
});
|
|
26
|
-
return Constructor;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function _extends() {
|
|
30
|
-
_extends = Object.assign || function (target) {
|
|
31
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
32
|
-
var source = arguments[i];
|
|
33
|
-
|
|
34
|
-
for (var key in source) {
|
|
35
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
36
|
-
target[key] = source[key];
|
|
37
|
-
}
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const LOG_PREFIX$2 = '[LE-AG-Websocket]';
|
|
5
|
+
const OPEN = 1;
|
|
6
|
+
class Websocket {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.buffer = [];
|
|
9
|
+
/**
|
|
10
|
+
* Every channel that should be subscribed, re-subscribed each time a new connection is identified.
|
|
11
|
+
*/
|
|
12
|
+
this.channels = new Map();
|
|
13
|
+
this.listeners = {};
|
|
14
|
+
this.closing = false;
|
|
15
|
+
this.reconnectAttempts = 0;
|
|
16
|
+
this.options = options;
|
|
17
|
+
if (this.options.host) {
|
|
18
|
+
this.connect();
|
|
19
|
+
}
|
|
38
20
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Object.defineProperty(subClass, "prototype", {
|
|
53
|
-
value: Object.create(superClass && superClass.prototype, {
|
|
54
|
-
constructor: {
|
|
55
|
-
value: subClass,
|
|
56
|
-
writable: true,
|
|
57
|
-
configurable: true
|
|
58
|
-
}
|
|
59
|
-
}),
|
|
60
|
-
writable: false
|
|
61
|
-
});
|
|
62
|
-
if (superClass) _setPrototypeOf(subClass, superClass);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function _getPrototypeOf(o) {
|
|
66
|
-
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
|
|
67
|
-
return o.__proto__ || Object.getPrototypeOf(o);
|
|
68
|
-
};
|
|
69
|
-
return _getPrototypeOf(o);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function _setPrototypeOf(o, p) {
|
|
73
|
-
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
|
74
|
-
o.__proto__ = p;
|
|
75
|
-
return o;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
return _setPrototypeOf(o, p);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function _isNativeReflectConstruct() {
|
|
82
|
-
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
83
|
-
if (Reflect.construct.sham) return false;
|
|
84
|
-
if (typeof Proxy === "function") return true;
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
|
88
|
-
return true;
|
|
89
|
-
} catch (e) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function _assertThisInitialized(self) {
|
|
95
|
-
if (self === void 0) {
|
|
96
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return self;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function _possibleConstructorReturn(self, call) {
|
|
103
|
-
if (call && (typeof call === "object" || typeof call === "function")) {
|
|
104
|
-
return call;
|
|
105
|
-
} else if (call !== void 0) {
|
|
106
|
-
throw new TypeError("Derived constructors may only return object or undefined");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return _assertThisInitialized(self);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function _createSuper(Derived) {
|
|
113
|
-
var hasNativeReflectConstruct = _isNativeReflectConstruct();
|
|
114
|
-
|
|
115
|
-
return function _createSuperInternal() {
|
|
116
|
-
var Super = _getPrototypeOf(Derived),
|
|
117
|
-
result;
|
|
118
|
-
|
|
119
|
-
if (hasNativeReflectConstruct) {
|
|
120
|
-
var NewTarget = _getPrototypeOf(this).constructor;
|
|
121
|
-
|
|
122
|
-
result = Reflect.construct(Super, arguments, NewTarget);
|
|
123
|
-
} else {
|
|
124
|
-
result = Super.apply(this, arguments);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return _possibleConstructorReturn(this, result);
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function _unsupportedIterableToArray(o, minLen) {
|
|
132
|
-
if (!o) return;
|
|
133
|
-
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
134
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
135
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
136
|
-
if (n === "Map" || n === "Set") return Array.from(o);
|
|
137
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function _arrayLikeToArray(arr, len) {
|
|
141
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
142
|
-
|
|
143
|
-
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
144
|
-
|
|
145
|
-
return arr2;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
149
|
-
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
|
|
150
|
-
|
|
151
|
-
if (!it) {
|
|
152
|
-
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
153
|
-
if (it) o = it;
|
|
154
|
-
var i = 0;
|
|
155
|
-
|
|
156
|
-
var F = function () {};
|
|
157
|
-
|
|
158
|
-
return {
|
|
159
|
-
s: F,
|
|
160
|
-
n: function () {
|
|
161
|
-
if (i >= o.length) return {
|
|
162
|
-
done: true
|
|
21
|
+
connect() {
|
|
22
|
+
const host = this.options.host;
|
|
23
|
+
this.debug(`Trying to connect to ${host}...`);
|
|
24
|
+
const websocket = new WebSocket(host);
|
|
25
|
+
this.websocket = websocket;
|
|
26
|
+
websocket.onopen = () => {
|
|
27
|
+
this.debug('Connected !');
|
|
28
|
+
this.reconnectAttempts = 0;
|
|
29
|
+
this.send({ event: 'whoami' });
|
|
30
|
+
while (this.buffer.length) {
|
|
31
|
+
this.send(this.buffer.shift());
|
|
32
|
+
}
|
|
33
|
+
this.startPing();
|
|
163
34
|
};
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
35
|
+
websocket.onmessage = (messageEvent) => {
|
|
36
|
+
this.handleMessage(messageEvent.data);
|
|
37
|
+
};
|
|
38
|
+
websocket.onerror = () => {
|
|
39
|
+
// A close event always follows an error, so reconnecting is handled in onclose.
|
|
40
|
+
this.debug('Connection error.');
|
|
41
|
+
};
|
|
42
|
+
websocket.onclose = () => {
|
|
43
|
+
if (this.websocket !== websocket) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.debug('Connection closed.');
|
|
47
|
+
this.stopPing();
|
|
48
|
+
this.socketId = undefined;
|
|
49
|
+
if (!this.closing) {
|
|
50
|
+
this.scheduleReconnect();
|
|
51
|
+
}
|
|
167
52
|
};
|
|
168
|
-
},
|
|
169
|
-
e: function (e) {
|
|
170
|
-
throw e;
|
|
171
|
-
},
|
|
172
|
-
f: F
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
var normalCompletion = true,
|
|
180
|
-
didErr = false,
|
|
181
|
-
err;
|
|
182
|
-
return {
|
|
183
|
-
s: function () {
|
|
184
|
-
it = it.call(o);
|
|
185
|
-
},
|
|
186
|
-
n: function () {
|
|
187
|
-
var step = it.next();
|
|
188
|
-
normalCompletion = step.done;
|
|
189
|
-
return step;
|
|
190
|
-
},
|
|
191
|
-
e: function (e) {
|
|
192
|
-
didErr = true;
|
|
193
|
-
err = e;
|
|
194
|
-
},
|
|
195
|
-
f: function () {
|
|
196
|
-
try {
|
|
197
|
-
if (!normalCompletion && it.return != null) it.return();
|
|
198
|
-
} finally {
|
|
199
|
-
if (didErr) throw err;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
class Connector {
|
|
206
|
-
/**
|
|
207
|
-
* Create a new class instance.
|
|
208
|
-
*/
|
|
209
|
-
constructor(options) {
|
|
210
|
-
/**
|
|
211
|
-
* Default connector options.
|
|
212
|
-
*/
|
|
213
|
-
this._defaultOptions = {
|
|
214
|
-
auth: {
|
|
215
|
-
headers: {},
|
|
216
|
-
},
|
|
217
|
-
authEndpoint: '/broadcasting/auth',
|
|
218
|
-
broadcaster: 'pusher',
|
|
219
|
-
csrfToken: null,
|
|
220
|
-
host: null,
|
|
221
|
-
key: null,
|
|
222
|
-
namespace: 'App.Events',
|
|
223
|
-
};
|
|
224
|
-
this.setOptions(options);
|
|
225
|
-
this.connect();
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Merge the custom options with the defaults.
|
|
229
|
-
*/
|
|
230
|
-
setOptions(options) {
|
|
231
|
-
this.options = Object.assign(this._defaultOptions, options);
|
|
232
|
-
if (this.csrfToken()) {
|
|
233
|
-
this.options.auth.headers['X-CSRF-TOKEN'] = this.csrfToken();
|
|
234
|
-
}
|
|
235
|
-
return options;
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Extract the CSRF token from the page.
|
|
239
|
-
*/
|
|
240
|
-
csrfToken() {
|
|
241
|
-
let selector;
|
|
242
|
-
if (typeof window !== 'undefined' && window['Laravel'] && window['Laravel'].csrfToken) {
|
|
243
|
-
return window['Laravel'].csrfToken;
|
|
244
|
-
}
|
|
245
|
-
else if (this.options.csrfToken) {
|
|
246
|
-
return this.options.csrfToken;
|
|
247
|
-
}
|
|
248
|
-
else if (typeof document !== 'undefined' &&
|
|
249
|
-
typeof document.querySelector === 'function' &&
|
|
250
|
-
(selector = document.querySelector('meta[name="csrf-token"]'))) {
|
|
251
|
-
return selector.getAttribute('content');
|
|
252
|
-
}
|
|
253
|
-
return null;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
var LOG_PREFIX = '[LE-AG-Websocket]';
|
|
258
|
-
var Websocket = /*#__PURE__*/function () {
|
|
259
|
-
function Websocket(options) {
|
|
260
|
-
_classCallCheck(this, Websocket);
|
|
261
|
-
|
|
262
|
-
this.buffer = [];
|
|
263
|
-
this.listeners = {};
|
|
264
|
-
this.internalListeners = {};
|
|
265
|
-
this.channelBacklog = [];
|
|
266
|
-
this.closing = false;
|
|
267
|
-
this.hasConnected = false;
|
|
268
|
-
this.options = options;
|
|
269
|
-
this.connect(this.options.host);
|
|
270
|
-
return this;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
_createClass(Websocket, [{
|
|
274
|
-
key: "connect",
|
|
275
|
-
value: function connect(host) {
|
|
276
|
-
var _this = this;
|
|
277
|
-
|
|
278
|
-
if (!host) {
|
|
279
|
-
this.options.debug && console.error(LOG_PREFIX + "Cannont connect without host !");
|
|
280
|
-
return;
|
|
281
53
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
_this.buffer.splice(0, 1);
|
|
310
|
-
} // Register events only once connected, or they won't be registered if connection failed/lost
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
_this.websocket.onmessage = function (messageEvent) {
|
|
314
|
-
var message = _this.parseMessage(messageEvent.data);
|
|
315
|
-
|
|
316
|
-
_this.options.debug && console.log(LOG_PREFIX + ' onmessage', messageEvent.data);
|
|
317
|
-
|
|
54
|
+
scheduleReconnect() {
|
|
55
|
+
var _a, _b;
|
|
56
|
+
const baseDelay = (_a = this.options.reconnectDelay) !== null && _a !== void 0 ? _a : 1000;
|
|
57
|
+
const maxDelay = (_b = this.options.maxReconnectDelay) !== null && _b !== void 0 ? _b : 30000;
|
|
58
|
+
const delay = Math.min(baseDelay * 2 ** this.reconnectAttempts, maxDelay);
|
|
59
|
+
this.reconnectAttempts++;
|
|
60
|
+
this.debug(`Connection lost, reconnecting in ${delay}ms...`);
|
|
61
|
+
clearTimeout(this.reconnectTimer);
|
|
62
|
+
this.reconnectTimer = setTimeout(() => this.connect(), delay);
|
|
63
|
+
}
|
|
64
|
+
startPing() {
|
|
65
|
+
var _a;
|
|
66
|
+
this.stopPing();
|
|
67
|
+
this.pingTimer = setInterval(() => {
|
|
68
|
+
if (this.socketIsReady()) {
|
|
69
|
+
this.debug('Sending ping');
|
|
70
|
+
this.send({ event: 'ping' });
|
|
71
|
+
}
|
|
72
|
+
}, (_a = this.options.pingInterval) !== null && _a !== void 0 ? _a : 60 * 1000);
|
|
73
|
+
}
|
|
74
|
+
stopPing() {
|
|
75
|
+
clearInterval(this.pingTimer);
|
|
76
|
+
this.pingTimer = undefined;
|
|
77
|
+
}
|
|
78
|
+
handleMessage(body) {
|
|
79
|
+
var _a;
|
|
80
|
+
const message = this.parseMessage(body);
|
|
318
81
|
if (!message) {
|
|
319
|
-
|
|
82
|
+
return;
|
|
320
83
|
}
|
|
321
|
-
|
|
84
|
+
this.debug('onmessage', body);
|
|
322
85
|
if (message.channel) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (_this.listeners[message.channel] && _this.listeners[message.channel][message.event]) {
|
|
326
|
-
_this.listeners[message.channel][message.event](message.data);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return;
|
|
86
|
+
this.dispatch(message.channel, message.event, message.data);
|
|
87
|
+
return;
|
|
330
88
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
89
|
+
if (message.event === 'whoami') {
|
|
90
|
+
this.socketId = (_a = message.data) === null || _a === void 0 ? void 0 : _a.socket_id;
|
|
91
|
+
this.debug(`Just set socketId to ${this.socketId}`);
|
|
92
|
+
this.channels.forEach((channel) => this.actuallySubscribe(channel));
|
|
334
93
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
});
|
|
94
|
+
}
|
|
95
|
+
dispatch(channelName, event, data) {
|
|
96
|
+
var _a, _b;
|
|
97
|
+
const callbacks = (_b = (_a = this.listeners[channelName]) === null || _a === void 0 ? void 0 : _a[event]) !== null && _b !== void 0 ? _b : [];
|
|
98
|
+
callbacks.slice().forEach((callback) => callback(data));
|
|
99
|
+
}
|
|
100
|
+
parseMessage(body) {
|
|
101
|
+
try {
|
|
102
|
+
return JSON.parse(body);
|
|
345
103
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.websocket.onclose = function () {
|
|
350
|
-
_this.options.debug && console.info('Connection closed.');
|
|
351
|
-
|
|
352
|
-
if (_this.closing) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
_this.hasConnected = false;
|
|
357
|
-
_this.options.debug && console.info('Connection lost, reconnecting...');
|
|
358
|
-
setTimeout(function () {
|
|
359
|
-
_this.socketId = undefined;
|
|
360
|
-
|
|
361
|
-
_this.connect(host);
|
|
362
|
-
}, 1000);
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
this.on('whoami', function (_ref) {
|
|
366
|
-
var socketId = _ref.socket_id;
|
|
367
|
-
_this.socketId = socketId;
|
|
368
|
-
_this.options.debug && console.log("".concat(LOG_PREFIX, " Just set socketId to ").concat(socketId)); // Handle the backlog and don't empty it, we'll need it if we lose connection
|
|
369
|
-
|
|
370
|
-
var channel;
|
|
371
|
-
|
|
372
|
-
var _iterator = _createForOfIteratorHelper(_this.channelBacklog),
|
|
373
|
-
_step;
|
|
374
|
-
|
|
375
|
-
try {
|
|
376
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
377
|
-
channel = _step.value;
|
|
378
|
-
|
|
379
|
-
_this.actuallySubscribe(channel);
|
|
104
|
+
catch (error) {
|
|
105
|
+
this.options.debug && console.error(error);
|
|
106
|
+
return undefined;
|
|
380
107
|
}
|
|
381
|
-
} catch (err) {
|
|
382
|
-
_iterator.e(err);
|
|
383
|
-
} finally {
|
|
384
|
-
_iterator.f();
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
}, {
|
|
389
|
-
key: "parseMessage",
|
|
390
|
-
value: function parseMessage(body) {
|
|
391
|
-
try {
|
|
392
|
-
return JSON.parse(body);
|
|
393
|
-
} catch (error) {
|
|
394
|
-
this.options.debug && console.error(error);
|
|
395
|
-
return undefined;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}, {
|
|
399
|
-
key: "getSocketId",
|
|
400
|
-
value: function getSocketId() {
|
|
401
|
-
return this.socketId;
|
|
402
|
-
}
|
|
403
|
-
}, {
|
|
404
|
-
key: "socketIsReady",
|
|
405
|
-
value: function socketIsReady() {
|
|
406
|
-
return this.websocket.readyState === this.websocket.OPEN;
|
|
407
|
-
}
|
|
408
|
-
}, {
|
|
409
|
-
key: "send",
|
|
410
|
-
value: function send(message) {
|
|
411
|
-
if (this.socketIsReady()) {
|
|
412
|
-
this.websocket.send(JSON.stringify(message));
|
|
413
|
-
return;
|
|
414
108
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
}, {
|
|
428
|
-
key: "subscribe",
|
|
429
|
-
value: function subscribe(channel) {
|
|
430
|
-
if (this.getSocketId()) {
|
|
431
|
-
this.actuallySubscribe(channel);
|
|
432
|
-
} else {
|
|
433
|
-
this.options.debug && console.log("".concat(LOG_PREFIX, " subscribe - push channel backlog for channel ").concat(channel.name));
|
|
434
|
-
this.channelBacklog.push(channel);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}, {
|
|
438
|
-
key: "actuallySubscribe",
|
|
439
|
-
value: function actuallySubscribe(channel) {
|
|
440
|
-
var _this2 = this;
|
|
441
|
-
|
|
442
|
-
if (channel.name.startsWith('private-') || channel.name.startsWith('presence-')) {
|
|
443
|
-
this.options.debug && console.log("".concat(LOG_PREFIX, " Sending auth request for channel ").concat(channel.name));
|
|
444
|
-
|
|
445
|
-
if (this.options.bearerToken) {
|
|
446
|
-
this.options.auth.headers['Authorization'] = 'Bearer ' + this.options.bearerToken;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
fetch(this.options.authEndpoint, {
|
|
450
|
-
method: 'POST',
|
|
451
|
-
headers: _extends({
|
|
452
|
-
'Content-Type': 'application/json'
|
|
453
|
-
}, this.options.auth.headers),
|
|
454
|
-
body: JSON.stringify({
|
|
455
|
-
socket_id: this.getSocketId(),
|
|
456
|
-
channel_name: channel.name
|
|
457
|
-
})
|
|
458
|
-
}).then(function (response) {
|
|
459
|
-
if (!response.ok) {
|
|
460
|
-
throw new Error("Auth request failed: ".concat(response.status));
|
|
109
|
+
getSocketId() {
|
|
110
|
+
return this.socketId;
|
|
111
|
+
}
|
|
112
|
+
socketIsReady() {
|
|
113
|
+
var _a;
|
|
114
|
+
return ((_a = this.websocket) === null || _a === void 0 ? void 0 : _a.readyState) === OPEN;
|
|
115
|
+
}
|
|
116
|
+
send(message) {
|
|
117
|
+
if (this.socketIsReady()) {
|
|
118
|
+
this.websocket.send(JSON.stringify(message));
|
|
119
|
+
return;
|
|
461
120
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
121
|
+
this.buffer.push(message);
|
|
122
|
+
}
|
|
123
|
+
close() {
|
|
124
|
+
var _a;
|
|
125
|
+
this.closing = true;
|
|
126
|
+
clearTimeout(this.reconnectTimer);
|
|
127
|
+
this.stopPing();
|
|
128
|
+
(_a = this.websocket) === null || _a === void 0 ? void 0 : _a.close();
|
|
129
|
+
}
|
|
130
|
+
subscribe(channel) {
|
|
131
|
+
this.channels.set(channel.name, channel);
|
|
132
|
+
if (this.socketId && this.socketIsReady()) {
|
|
133
|
+
this.actuallySubscribe(channel);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
this.debug(`Channel ${channel.name} will be subscribed once connected`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
actuallySubscribe(channel) {
|
|
140
|
+
if (!channel.name.startsWith('private-') && !channel.name.startsWith('presence-')) {
|
|
141
|
+
this.debug(`Subscribing to channel ${channel.name}`);
|
|
142
|
+
this.send({ event: 'subscribe', data: { channel: channel.name } });
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const socketId = this.socketId;
|
|
146
|
+
this.debug(`Sending auth request for channel ${channel.name}`);
|
|
147
|
+
this.authorize(channel.name, socketId).then((data) => {
|
|
148
|
+
// Skip outdated authorizations: the connection changed or the channel was left meanwhile.
|
|
149
|
+
if (socketId !== this.socketId || this.channels.get(channel.name) !== channel) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
this.debug(`Subscribing to private channel ${channel.name}`);
|
|
153
|
+
this.send({ event: 'subscribe', data: Object.assign({ channel: channel.name }, data) });
|
|
154
|
+
}).catch((error) => {
|
|
155
|
+
this.debug(`Auth request for channel ${channel.name} failed`, error);
|
|
156
|
+
this.dispatch(channel.name, 'error', error);
|
|
472
157
|
});
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
158
|
+
}
|
|
159
|
+
authorize(channelName, socketId) {
|
|
160
|
+
var _a, _b, _c;
|
|
161
|
+
const channelAuthorization = (_a = this.options.channelAuthorization) !== null && _a !== void 0 ? _a : {};
|
|
162
|
+
if (typeof channelAuthorization.customHandler === 'function') {
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
channelAuthorization.customHandler({ socketId, channelName }, (error, data) => {
|
|
165
|
+
var _a;
|
|
166
|
+
if (error) {
|
|
167
|
+
reject(this.authorizationError(error, (_a = error === null || error === void 0 ? void 0 : error.status) !== null && _a !== void 0 ? _a : null));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
resolve(data);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
483
174
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
delete this.listeners[channel.name];
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}, {
|
|
503
|
-
key: "on",
|
|
504
|
-
value: function on(event) {
|
|
505
|
-
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
506
|
-
this.options.debug && console.log("".concat(LOG_PREFIX, " on event ").concat(event, " ..."));
|
|
507
|
-
this.internalListeners[event] = callback;
|
|
508
|
-
}
|
|
509
|
-
}, {
|
|
510
|
-
key: "bind",
|
|
511
|
-
value: function bind(channel, event, callback) {
|
|
512
|
-
this.options.debug && console.log("".concat(LOG_PREFIX, " bind event ").concat(event, " for channel ").concat(channel.name, " ..."));
|
|
513
|
-
|
|
514
|
-
if (!this.listeners[channel.name]) {
|
|
515
|
-
this.listeners[channel.name] = {};
|
|
175
|
+
return fetch((_b = channelAuthorization.endpoint) !== null && _b !== void 0 ? _b : this.options.authEndpoint, {
|
|
176
|
+
method: 'POST',
|
|
177
|
+
headers: Object.assign(Object.assign({ 'Content-Type': 'application/json', 'Accept': 'application/json' }, (_c = this.options.auth) === null || _c === void 0 ? void 0 : _c.headers), channelAuthorization.headers),
|
|
178
|
+
body: JSON.stringify({
|
|
179
|
+
socket_id: socketId,
|
|
180
|
+
channel_name: channelName,
|
|
181
|
+
}),
|
|
182
|
+
}).then((response) => {
|
|
183
|
+
if (!response.ok) {
|
|
184
|
+
throw this.authorizationError(new Error(`Auth request failed: ${response.status}`), response.status);
|
|
185
|
+
}
|
|
186
|
+
return response.json();
|
|
187
|
+
}, (error) => {
|
|
188
|
+
throw this.authorizationError(error, null);
|
|
189
|
+
});
|
|
516
190
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
}, {
|
|
521
|
-
key: "unbindEvent",
|
|
522
|
-
value: function unbindEvent(channel, event) {
|
|
523
|
-
var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
524
|
-
this.options.debug && console.log("".concat(LOG_PREFIX, " unbind event ").concat(event, " for channel ").concat(channel.name, " ..."));
|
|
525
|
-
|
|
526
|
-
if (this.internalListeners[event] && (callback === null || this.internalListeners[event] === callback)) {
|
|
527
|
-
delete this.internalListeners[event];
|
|
191
|
+
authorizationError(error, status) {
|
|
192
|
+
return { type: 'AuthError', status, error };
|
|
528
193
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* This class represents a basic channel.
|
|
567
|
-
*/
|
|
568
|
-
class Channel {
|
|
569
|
-
/**
|
|
570
|
-
* Listen for a whisper event on the channel instance.
|
|
571
|
-
*/
|
|
572
|
-
listenForWhisper(event, callback) {
|
|
573
|
-
return this.listen('.client-' + event, callback);
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* Listen for an event on the channel instance.
|
|
577
|
-
*/
|
|
578
|
-
notification(callback) {
|
|
579
|
-
return this.listen('.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated', callback);
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* Stop listening for a whisper event on the channel instance.
|
|
583
|
-
*/
|
|
584
|
-
stopListeningForWhisper(event, callback) {
|
|
585
|
-
return this.stopListening('.client-' + event, callback);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
var LOG_PREFIX$1 = '[LE-AG-Channel]';
|
|
590
|
-
/**
|
|
591
|
-
* This class represents a Pusher channel.
|
|
592
|
-
*/
|
|
593
|
-
|
|
594
|
-
var Channel$1 = /*#__PURE__*/function (_BaseChannel) {
|
|
595
|
-
_inherits(Channel, _BaseChannel);
|
|
596
|
-
|
|
597
|
-
var _super = _createSuper(Channel);
|
|
194
|
+
unsubscribe(channel) {
|
|
195
|
+
this.debug(`unsubscribe for channel ${channel.name}`);
|
|
196
|
+
if (this.channels.get(channel.name) === channel) {
|
|
197
|
+
this.channels.delete(channel.name);
|
|
198
|
+
delete this.listeners[channel.name];
|
|
199
|
+
}
|
|
200
|
+
if (this.socketId && this.socketIsReady()) {
|
|
201
|
+
this.send({ event: 'unsubscribe', data: { channel: channel.name } });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
bind(channel, event, callback) {
|
|
205
|
+
var _a, _b;
|
|
206
|
+
var _c, _d, _e;
|
|
207
|
+
this.debug(`bind event ${event} for channel ${channel.name} ...`);
|
|
208
|
+
(_a = (_c = this.listeners)[_d = channel.name]) !== null && _a !== void 0 ? _a : (_c[_d] = {});
|
|
209
|
+
(_b = (_e = this.listeners[channel.name])[event]) !== null && _b !== void 0 ? _b : (_e[event] = []);
|
|
210
|
+
this.listeners[channel.name][event].push(callback);
|
|
211
|
+
}
|
|
212
|
+
unbind(channel, event, callback) {
|
|
213
|
+
var _a;
|
|
214
|
+
this.debug(`unbind event ${event} for channel ${channel.name} ...`);
|
|
215
|
+
const callbacks = (_a = this.listeners[channel.name]) === null || _a === void 0 ? void 0 : _a[event];
|
|
216
|
+
if (!callbacks) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (callback) {
|
|
220
|
+
this.listeners[channel.name][event] = callbacks.filter((existing) => existing !== callback);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
delete this.listeners[channel.name][event];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
debug(...messages) {
|
|
227
|
+
this.options.debug && console.log(LOG_PREFIX$2, ...messages);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
598
230
|
|
|
599
231
|
/**
|
|
600
|
-
*
|
|
232
|
+
* Formats event names the same way laravel-echo does, so `listen('OrderCreated')` matches
|
|
233
|
+
* `App\Events\OrderCreated` and `listen('.custom-name')` matches `custom-name`.
|
|
601
234
|
*/
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
235
|
+
class EventFormatter {
|
|
236
|
+
constructor(namespace) {
|
|
237
|
+
this.namespace = namespace;
|
|
238
|
+
}
|
|
239
|
+
format(event) {
|
|
240
|
+
if (['.', '\\'].includes(event.charAt(0))) {
|
|
241
|
+
return event.substring(1);
|
|
242
|
+
}
|
|
243
|
+
if (this.namespace) {
|
|
244
|
+
event = this.namespace + '.' + event;
|
|
245
|
+
}
|
|
246
|
+
return event.replace(/\./g, '\\');
|
|
247
|
+
}
|
|
248
|
+
setNamespace(namespace) {
|
|
249
|
+
this.namespace = namespace;
|
|
250
|
+
}
|
|
616
251
|
}
|
|
617
|
-
/**
|
|
618
|
-
* Subscribe to a Pusher channel.
|
|
619
|
-
*/
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
_createClass(Channel, [{
|
|
623
|
-
key: "subscribe",
|
|
624
|
-
value: function subscribe() {
|
|
625
|
-
this.options["debug"] && console.log("".concat(LOG_PREFIX$1, " subscribe for channel ").concat(this.name, " ..."));
|
|
626
|
-
this.socket.subscribe(this);
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* Unsubscribe from a Pusher channel.
|
|
630
|
-
*/
|
|
631
|
-
|
|
632
|
-
}, {
|
|
633
|
-
key: "unsubscribe",
|
|
634
|
-
value: function unsubscribe() {
|
|
635
|
-
this.options["debug"] && console.log("".concat(LOG_PREFIX$1, " unsubscribe for channel ").concat(this.name, " ..."));
|
|
636
|
-
this.socket.unsubscribe(this);
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* Listen for an event on the channel instance.
|
|
640
|
-
*/
|
|
641
|
-
|
|
642
|
-
}, {
|
|
643
|
-
key: "listen",
|
|
644
|
-
value: function listen(event, callback) {
|
|
645
|
-
this.options["debug"] && console.log("".concat(LOG_PREFIX$1, " listen to ").concat(event, " for channel ").concat(this.name, " ..."));
|
|
646
|
-
this.on(this.eventFormatter.format(event), callback);
|
|
647
|
-
return this;
|
|
648
|
-
}
|
|
649
|
-
/**
|
|
650
|
-
* Stop listening for an event on the channel instance.
|
|
651
|
-
*/
|
|
652
|
-
|
|
653
|
-
}, {
|
|
654
|
-
key: "stopListening",
|
|
655
|
-
value: function stopListening(event, callback) {
|
|
656
|
-
this.options["debug"] && console.log("".concat(LOG_PREFIX$1, " stop listening to ").concat(event, " for channel ").concat(this.name, " ..."));
|
|
657
|
-
this.socket.unbindEvent(this, event, callback);
|
|
658
|
-
return this;
|
|
659
|
-
}
|
|
660
|
-
/**
|
|
661
|
-
* Register a callback to be called anytime a subscription succeeds.
|
|
662
|
-
*/
|
|
663
|
-
|
|
664
|
-
}, {
|
|
665
|
-
key: "subscribed",
|
|
666
|
-
value: function subscribed(callback) {
|
|
667
|
-
this.options["debug"] && console.log("".concat(LOG_PREFIX$1, " subscribed for channel ").concat(this.name, " ..."));
|
|
668
|
-
this.on('subscription_succeeded', function () {
|
|
669
|
-
callback();
|
|
670
|
-
});
|
|
671
|
-
return this;
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* Register a callback to be called anytime a subscription error occurs.
|
|
675
|
-
*/
|
|
676
|
-
|
|
677
|
-
}, {
|
|
678
|
-
key: "error",
|
|
679
|
-
value: function error(callback) {
|
|
680
|
-
this.options["debug"] && console.log("".concat(LOG_PREFIX$1, " error for channel ").concat(this.name, " ..."));
|
|
681
|
-
this.on('error', function (status) {
|
|
682
|
-
callback(status);
|
|
683
|
-
});
|
|
684
|
-
return this;
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Bind a channel to an event.
|
|
688
|
-
*/
|
|
689
|
-
|
|
690
|
-
}, {
|
|
691
|
-
key: "on",
|
|
692
|
-
value: function on(event, callback) {
|
|
693
|
-
this.options["debug"] && console.log("".concat(LOG_PREFIX$1, " on ").concat(event, " for channel ").concat(this.name, " ..."));
|
|
694
|
-
this.socket.bind(this, event, callback);
|
|
695
|
-
return this;
|
|
696
|
-
}
|
|
697
|
-
}, {
|
|
698
|
-
key: "whisper",
|
|
699
|
-
value: function whisper(event, data) {
|
|
700
|
-
var channel = this.name;
|
|
701
|
-
var formattedEvent = "client-" + event;
|
|
702
|
-
this.socket.send({
|
|
703
|
-
"event": formattedEvent,
|
|
704
|
-
data: data,
|
|
705
|
-
channel: channel
|
|
706
|
-
});
|
|
707
|
-
return this;
|
|
708
|
-
}
|
|
709
|
-
}, {
|
|
710
|
-
key: "here",
|
|
711
|
-
value: function here(callback) {
|
|
712
|
-
// TODO: implement
|
|
713
|
-
return this;
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* Listen for someone joining the channel.
|
|
717
|
-
*/
|
|
718
|
-
|
|
719
|
-
}, {
|
|
720
|
-
key: "joining",
|
|
721
|
-
value: function joining(callback) {
|
|
722
|
-
// TODO: implement
|
|
723
|
-
return this;
|
|
724
|
-
}
|
|
725
|
-
/**
|
|
726
|
-
* Listen for someone leaving the channel.
|
|
727
|
-
*/
|
|
728
|
-
|
|
729
|
-
}, {
|
|
730
|
-
key: "leaving",
|
|
731
|
-
value: function leaving(callback) {
|
|
732
|
-
// TODO: implement
|
|
733
|
-
return this;
|
|
734
|
-
}
|
|
735
|
-
}]);
|
|
736
|
-
|
|
737
|
-
return Channel;
|
|
738
|
-
}(Channel);
|
|
739
|
-
|
|
740
|
-
var broadcaster = function broadcaster(options) {
|
|
741
|
-
return new Connector$1(options);
|
|
742
|
-
};
|
|
743
|
-
var LOG_PREFIX$2 = '[LE-AG-Connector]';
|
|
744
|
-
var Connector$1 = /*#__PURE__*/function (_BaseConnector) {
|
|
745
|
-
_inherits(Connector, _BaseConnector);
|
|
746
|
-
|
|
747
|
-
var _super = _createSuper(Connector);
|
|
748
252
|
|
|
253
|
+
const LOG_PREFIX$1 = '[LE-AG-Channel]';
|
|
254
|
+
const NOTIFICATION_EVENT = '.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated';
|
|
749
255
|
/**
|
|
750
|
-
*
|
|
256
|
+
* A channel on the API Gateway websocket. It implements the public, private and presence channel
|
|
257
|
+
* interfaces of laravel-echo (v1 and v2) without extending its internal classes.
|
|
751
258
|
*/
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
259
|
+
class Channel {
|
|
260
|
+
/**
|
|
261
|
+
* Create a new class instance.
|
|
262
|
+
*/
|
|
263
|
+
constructor(socket, name, options) {
|
|
264
|
+
this.name = name;
|
|
265
|
+
this.socket = socket;
|
|
266
|
+
this.options = options;
|
|
267
|
+
this.eventFormatter = new EventFormatter(this.options.namespace);
|
|
268
|
+
this.subscribe();
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Subscribe to the channel.
|
|
272
|
+
*/
|
|
273
|
+
subscribe() {
|
|
274
|
+
this.options.debug && console.log(`${LOG_PREFIX$1} subscribe for channel ${this.name} ...`);
|
|
275
|
+
this.socket.subscribe(this);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Unsubscribe from the channel.
|
|
279
|
+
*/
|
|
280
|
+
unsubscribe() {
|
|
281
|
+
this.options.debug && console.log(`${LOG_PREFIX$1} unsubscribe for channel ${this.name} ...`);
|
|
282
|
+
this.socket.unsubscribe(this);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Listen for an event on the channel instance.
|
|
286
|
+
*/
|
|
287
|
+
listen(event, callback) {
|
|
288
|
+
this.options.debug && console.log(`${LOG_PREFIX$1} listen to ${event} for channel ${this.name} ...`);
|
|
289
|
+
return this.on(this.eventFormatter.format(event), callback);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Stop listening for an event on the channel instance. Without a callback, every listener of the event is removed.
|
|
293
|
+
*/
|
|
294
|
+
stopListening(event, callback) {
|
|
295
|
+
this.options.debug && console.log(`${LOG_PREFIX$1} stop listening to ${event} for channel ${this.name} ...`);
|
|
296
|
+
this.socket.unbind(this, this.eventFormatter.format(event), callback);
|
|
297
|
+
return this;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Listen for a whisper event on the channel instance.
|
|
301
|
+
*/
|
|
302
|
+
listenForWhisper(event, callback) {
|
|
303
|
+
return this.listen('.client-' + event, callback);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Stop listening for a whisper event on the channel instance.
|
|
307
|
+
*/
|
|
308
|
+
stopListeningForWhisper(event, callback) {
|
|
309
|
+
return this.stopListening('.client-' + event, callback);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Listen for an event on the channel instance.
|
|
313
|
+
*/
|
|
314
|
+
notification(callback) {
|
|
315
|
+
return this.listen(NOTIFICATION_EVENT, callback);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Stop listening for notification events on the channel instance.
|
|
319
|
+
*/
|
|
320
|
+
stopListeningForNotification(callback) {
|
|
321
|
+
return this.stopListening(NOTIFICATION_EVENT, callback);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Register a callback to be called anytime a subscription succeeds.
|
|
325
|
+
*/
|
|
326
|
+
subscribed(callback) {
|
|
327
|
+
return this.on('subscription_succeeded', () => {
|
|
328
|
+
callback();
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Register a callback to be called anytime a subscription or authorization error occurs.
|
|
333
|
+
*/
|
|
334
|
+
error(callback) {
|
|
335
|
+
return this.on('error', callback);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Bind a channel to an event.
|
|
339
|
+
*/
|
|
340
|
+
on(event, callback) {
|
|
341
|
+
this.options.debug && console.log(`${LOG_PREFIX$1} on ${event} for channel ${this.name} ...`);
|
|
342
|
+
this.socket.bind(this, event, callback);
|
|
343
|
+
return this;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Send a client event to the other members of the channel.
|
|
347
|
+
*/
|
|
348
|
+
whisper(event, data) {
|
|
349
|
+
this.socket.send({
|
|
350
|
+
event: 'client-' + event,
|
|
351
|
+
channel: this.name,
|
|
352
|
+
data,
|
|
353
|
+
});
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Presence channels are not supported yet: member tracking is not implemented on the server.
|
|
358
|
+
*/
|
|
359
|
+
here(_callback) {
|
|
360
|
+
return this;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Presence channels are not supported yet: member tracking is not implemented on the server.
|
|
364
|
+
*/
|
|
365
|
+
joining(_callback) {
|
|
366
|
+
return this;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Presence channels are not supported yet: member tracking is not implemented on the server.
|
|
370
|
+
*/
|
|
371
|
+
leaving(_callback) {
|
|
372
|
+
return this;
|
|
373
|
+
}
|
|
764
374
|
}
|
|
375
|
+
|
|
376
|
+
const LOG_PREFIX = '[LE-AG-Connector]';
|
|
765
377
|
/**
|
|
766
|
-
*
|
|
378
|
+
* Laravel Echo connector for API Gateway websockets.
|
|
379
|
+
*
|
|
380
|
+
* It does not extend laravel-echo's internal classes, so it works with laravel-echo v1 and v2:
|
|
381
|
+
* both create custom connectors with `new options.broadcaster(options)`.
|
|
767
382
|
*/
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
// });
|
|
781
|
-
//
|
|
782
|
-
// return this.socket;
|
|
783
|
-
}
|
|
784
|
-
/**
|
|
785
|
-
* Get a channel instance by name.
|
|
786
|
-
*/
|
|
787
|
-
|
|
788
|
-
}, {
|
|
789
|
-
key: "channel",
|
|
790
|
-
value: function channel(name) {
|
|
791
|
-
if (!this.channels[name]) {
|
|
792
|
-
this.channels[name] = new Channel$1(this.socket, name, this.options);
|
|
383
|
+
class Connector {
|
|
384
|
+
/**
|
|
385
|
+
* Create a new class instance. Without a host no connection is opened, which keeps
|
|
386
|
+
* laravel-echo v2's `new broadcaster()` capability check free of side effects.
|
|
387
|
+
*/
|
|
388
|
+
constructor(options = {}) {
|
|
389
|
+
/**
|
|
390
|
+
* All of the subscribed channel names.
|
|
391
|
+
*/
|
|
392
|
+
this.channels = {};
|
|
393
|
+
this.setOptions(options);
|
|
394
|
+
this.connect();
|
|
793
395
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
396
|
+
/**
|
|
397
|
+
* Merge the custom options with the defaults and add the CSRF and bearer token headers.
|
|
398
|
+
*/
|
|
399
|
+
setOptions(options) {
|
|
400
|
+
var _a, _b;
|
|
401
|
+
this.options = Object.assign(Object.assign(Object.assign({}, Connector._defaultOptions), options), { auth: {
|
|
402
|
+
headers: Object.assign({}, ((_b = (_a = options.auth) === null || _a === void 0 ? void 0 : _a.headers) !== null && _b !== void 0 ? _b : {})),
|
|
403
|
+
} });
|
|
404
|
+
const csrfToken = this.csrfToken();
|
|
405
|
+
if (csrfToken) {
|
|
406
|
+
this.options.auth.headers['X-CSRF-TOKEN'] = csrfToken;
|
|
407
|
+
}
|
|
408
|
+
if (this.options.bearerToken) {
|
|
409
|
+
this.options.auth.headers['Authorization'] = 'Bearer ' + this.options.bearerToken;
|
|
410
|
+
}
|
|
806
411
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
412
|
+
/**
|
|
413
|
+
* Extract the CSRF token from the page.
|
|
414
|
+
*/
|
|
415
|
+
csrfToken() {
|
|
416
|
+
var _a, _b, _c;
|
|
417
|
+
if (typeof window !== 'undefined' && ((_a = window.Laravel) === null || _a === void 0 ? void 0 : _a.csrfToken)) {
|
|
418
|
+
return window.Laravel.csrfToken;
|
|
419
|
+
}
|
|
420
|
+
if (this.options.csrfToken) {
|
|
421
|
+
return this.options.csrfToken;
|
|
422
|
+
}
|
|
423
|
+
if (typeof document !== 'undefined' && typeof document.querySelector === 'function') {
|
|
424
|
+
return (_c = (_b = document.querySelector('meta[name="csrf-token"]')) === null || _b === void 0 ? void 0 : _b.getAttribute('content')) !== null && _c !== void 0 ? _c : null;
|
|
425
|
+
}
|
|
426
|
+
return null;
|
|
819
427
|
}
|
|
428
|
+
/**
|
|
429
|
+
* Create a fresh websocket connection.
|
|
430
|
+
*/
|
|
431
|
+
connect() {
|
|
432
|
+
this.options.debug && console.log(LOG_PREFIX + ' Connect ...');
|
|
433
|
+
this.socket = new Websocket(this.options);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Listen for an event on a channel instance.
|
|
437
|
+
*/
|
|
438
|
+
listen(name, event, callback) {
|
|
439
|
+
return this.channel(name).listen(event, callback);
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Get a channel instance by name.
|
|
443
|
+
*/
|
|
444
|
+
channel(name) {
|
|
445
|
+
if (!this.channels[name]) {
|
|
446
|
+
this.channels[name] = new Channel(this.socket, name, this.options);
|
|
447
|
+
}
|
|
448
|
+
return this.channels[name];
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Get a private channel instance by name.
|
|
452
|
+
*/
|
|
453
|
+
privateChannel(name) {
|
|
454
|
+
return this.channel('private-' + name);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Get a presence channel instance by name.
|
|
458
|
+
*/
|
|
459
|
+
presenceChannel(name) {
|
|
460
|
+
return this.channel('presence-' + name);
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Leave the given channel, as well as its private and presence variants.
|
|
464
|
+
*/
|
|
465
|
+
leave(name) {
|
|
466
|
+
[name, 'private-' + name, 'presence-' + name].forEach((channelName) => {
|
|
467
|
+
this.leaveChannel(channelName);
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Leave the given channel.
|
|
472
|
+
*/
|
|
473
|
+
leaveChannel(name) {
|
|
474
|
+
if (this.channels[name]) {
|
|
475
|
+
this.channels[name].unsubscribe();
|
|
476
|
+
delete this.channels[name];
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Get the socket ID for the connection.
|
|
481
|
+
*/
|
|
482
|
+
socketId() {
|
|
483
|
+
return this.socket.getSocketId();
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Disconnect socket connection.
|
|
487
|
+
*/
|
|
488
|
+
disconnect() {
|
|
489
|
+
this.options.debug && console.log(LOG_PREFIX + ' Disconnect ...');
|
|
490
|
+
this.socket.close();
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Default connector options, matching laravel-echo's defaults.
|
|
495
|
+
*/
|
|
496
|
+
Connector._defaultOptions = {
|
|
497
|
+
auth: {
|
|
498
|
+
headers: {},
|
|
499
|
+
},
|
|
500
|
+
authEndpoint: '/broadcasting/auth',
|
|
501
|
+
csrfToken: null,
|
|
502
|
+
bearerToken: null,
|
|
503
|
+
host: null,
|
|
504
|
+
namespace: 'App.Events',
|
|
505
|
+
};
|
|
506
|
+
/**
|
|
507
|
+
* Kept for backwards compatibility: `new Echo({ broadcaster })`. A function declaration (not an arrow
|
|
508
|
+
* function) so laravel-echo can call it with `new`.
|
|
509
|
+
*/
|
|
510
|
+
function broadcaster(options) {
|
|
511
|
+
return new Connector(options);
|
|
512
|
+
}
|
|
820
513
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
*/
|
|
826
|
-
|
|
827
|
-
}, {
|
|
828
|
-
key: "leave",
|
|
829
|
-
value: function leave(name) {
|
|
830
|
-
var _this2 = this;
|
|
831
|
-
|
|
832
|
-
var channels = [name, 'private-' + name, 'presence-' + name];
|
|
833
|
-
channels.forEach(function (name) {
|
|
834
|
-
_this2.leaveChannel(name);
|
|
835
|
-
});
|
|
836
|
-
}
|
|
837
|
-
/**
|
|
838
|
-
* Leave the given channel.
|
|
839
|
-
*/
|
|
840
|
-
|
|
841
|
-
}, {
|
|
842
|
-
key: "leaveChannel",
|
|
843
|
-
value: function leaveChannel(name) {
|
|
844
|
-
if (this.channels[name]) {
|
|
845
|
-
this.channels[name].unsubscribe();
|
|
846
|
-
delete this.channels[name];
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
/**
|
|
850
|
-
* Get the socket ID for the connection.
|
|
851
|
-
*/
|
|
852
|
-
|
|
853
|
-
}, {
|
|
854
|
-
key: "socketId",
|
|
855
|
-
value: function socketId() {
|
|
856
|
-
return this.socket.getSocketId();
|
|
857
|
-
}
|
|
858
|
-
/**
|
|
859
|
-
* Disconnect socket connection.
|
|
860
|
-
*/
|
|
861
|
-
|
|
862
|
-
}, {
|
|
863
|
-
key: "disconnect",
|
|
864
|
-
value: function disconnect() {
|
|
865
|
-
this.options.debug && console.log(LOG_PREFIX$2 + 'Disconnect ...');
|
|
866
|
-
this.socket.close();
|
|
867
|
-
}
|
|
868
|
-
}]);
|
|
869
|
-
|
|
870
|
-
return Connector;
|
|
871
|
-
}(Connector);
|
|
872
|
-
|
|
873
|
-
exports.Connector = Connector$1;
|
|
874
|
-
exports.broadcaster = broadcaster;
|
|
875
|
-
|
|
876
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
514
|
+
exports.Channel = Channel;
|
|
515
|
+
exports.Connector = Connector;
|
|
516
|
+
exports.EventFormatter = EventFormatter;
|
|
517
|
+
exports.broadcaster = broadcaster;
|
|
877
518
|
|
|
878
|
-
|
|
519
|
+
return exports;
|
|
879
520
|
|
|
880
|
-
}({})
|
|
521
|
+
})({});
|