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.
@@ -1,109 +1,344 @@
1
1
  import WS from "jest-websocket-mock";
2
2
  import { Connector } from "../js-src/Connector";
3
3
  import { Channel } from "../js-src/Channel";
4
-
5
- const mockedHost = 'ws://localhost:1234';
4
+ import { flushPromises, identify, mockedHost, mockFetchResponse, restartServer } from "./helpers";
6
5
 
7
6
  describe('Connector', () => {
8
7
  let server: WS;
8
+ let connector: Connector;
9
9
 
10
10
  beforeEach(() => {
11
- jest.useRealTimers();
12
- server = new WS(mockedHost);
11
+ server = new WS(mockedHost, { jsonProtocol: true });
13
12
  });
14
13
 
15
14
  afterEach(() => {
16
- server.close()
15
+ connector?.disconnect();
16
+ connector = undefined;
17
+ WS.clean();
18
+ jest.restoreAllMocks();
17
19
  });
18
20
 
19
21
  test('socket id is correctly set', async () => {
20
- const connector = new Connector({
21
- host: mockedHost,
22
- })
23
-
24
- await server.connected;
22
+ connector = new Connector({ host: mockedHost });
25
23
 
26
- await expect(server).toReceiveMessage('{"event":"whoami"}');
27
- server.send('{"event":"whoami","data":{"socket_id":"test-socket-id"}}')
24
+ await identify(server, 'test-socket-id');
28
25
 
29
- expect(connector.socketId()).toBe('test-socket-id')
30
- })
26
+ expect(connector.socketId()).toBe('test-socket-id');
27
+ });
31
28
 
32
29
  test('we reconnect to the server on error', async () => {
33
- const connector = new Connector({
34
- host: mockedHost,
35
- })
30
+ connector = new Connector({ host: mockedHost, reconnectDelay: 10 });
36
31
 
37
- await server.connected;
38
- await expect(server).toReceiveMessage('{"event":"whoami"}');
39
- server.send('{"event":"whoami","data":{"socket_id":"test-socket-id"}}')
32
+ await identify(server, 'test-socket-id');
40
33
 
41
- server.close();
42
- await server.closed;
43
- server.server.stop(() => (server = new WS(mockedHost)));
34
+ server = await restartServer(server);
35
+ await identify(server, 'test-socket-id2');
44
36
 
45
- await server.connected;
46
- await expect(server).toReceiveMessage('{"event":"whoami"}');
47
- server.send('{"event":"whoami","data":{"socket_id":"test-socket-id2"}}')
37
+ expect(connector.socketId()).toBe('test-socket-id2');
38
+ });
48
39
 
49
- expect(connector.socketId()).toBe('test-socket-id2')
50
- })
40
+ test('we only open one new connection per reconnect', async () => {
41
+ connector = new Connector({ host: mockedHost, reconnectDelay: 10 });
51
42
 
52
- test('we can subscribe to a channel and listen to events', async () => {
53
- const connector = new Connector({
54
- host: mockedHost,
55
- })
43
+ await identify(server, 'test-socket-id');
56
44
 
57
- await server.connected;
45
+ server = await restartServer(server);
46
+ await identify(server, 'test-socket-id2');
47
+ await new Promise((resolve) => setTimeout(resolve, 50));
58
48
 
59
- await expect(server).toReceiveMessage('{"event":"whoami"}');
60
- server.send('{"event":"whoami","data":{"socket_id":"test-socket-id"}}')
49
+ expect(server.server.clients()).toHaveLength(1);
50
+ });
61
51
 
62
- const channel = connector.channel('my-test-channel')
52
+ test('we keep retrying until the server is available, with a single connection', async () => {
53
+ WS.clean();
63
54
 
64
- await expect(server).toReceiveMessage('{"event":"subscribe","data":{"channel":"my-test-channel"}}');
55
+ connector = new Connector({ host: mockedHost, reconnectDelay: 5, maxReconnectDelay: 20 });
56
+ await new Promise((resolve) => setTimeout(resolve, 60));
65
57
 
66
- server.send('{"event":"subscription_succeeded","channel":"my-test-channel"}')
58
+ server = new WS(mockedHost, { jsonProtocol: true });
59
+ await identify(server, 'test-socket-id');
60
+ await new Promise((resolve) => setTimeout(resolve, 60));
67
61
 
68
- expect(channel).toBeInstanceOf(Channel)
62
+ expect(connector.socketId()).toBe('test-socket-id');
63
+ expect(server.server.clients()).toHaveLength(1);
64
+ });
65
+
66
+ test('we can subscribe to a channel and listen to events', async () => {
67
+ connector = new Connector({ host: mockedHost });
68
+
69
+ await identify(server, 'test-socket-id');
70
+
71
+ const channel = connector.channel('my-test-channel');
72
+
73
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'my-test-channel' } });
74
+
75
+ expect(channel).toBeInstanceOf(Channel);
69
76
 
70
77
  const handler1 = jest.fn();
71
78
  const handler2 = jest.fn();
72
79
 
73
- channel.on('my-test-event', handler1)
80
+ channel.listen('.my-test-event', handler1);
74
81
 
75
- server.send('{"event":"my-test-event","channel":"my-test-channel","data":{}}')
82
+ server.send({ event: 'my-test-event', channel: 'my-test-channel', data: { id: 1 } });
76
83
 
77
- expect(handler1).toBeCalled();
78
- expect(handler2).not.toBeCalled();
79
- })
84
+ expect(handler1).toHaveBeenCalledWith({ id: 1 });
85
+ expect(handler2).not.toHaveBeenCalled();
86
+ });
80
87
 
81
- test('we can send a whisper event', async () => {
82
- const connector = new Connector({
83
- host: mockedHost,
84
- })
88
+ test('channels subscribed before the connection is ready are subscribed once identified', async () => {
89
+ connector = new Connector({ host: mockedHost });
85
90
 
86
- await server.connected;
91
+ connector.channel('early-channel');
87
92
 
88
- await expect(server).toReceiveMessage('{"event":"whoami"}');
89
- server.send('{"event":"whoami","data":{"socket_id":"test-socket-id"}}')
93
+ await identify(server, 'test-socket-id');
90
94
 
91
- const channel = connector.channel('my-test-channel')
95
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'early-channel' } });
96
+ });
97
+
98
+ test('every listener of the same event is called', async () => {
99
+ connector = new Connector({ host: mockedHost });
100
+ await identify(server, 'test-socket-id');
101
+
102
+ const handler1 = jest.fn();
103
+ const handler2 = jest.fn();
104
+
105
+ connector.channel('my-test-channel').listen('.my-test-event', handler1);
106
+ connector.channel('my-test-channel').listen('.my-test-event', handler2);
107
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'my-test-channel' } });
92
108
 
93
- await expect(server).toReceiveMessage('{"event":"subscribe","data":{"channel":"my-test-channel"}}');
109
+ server.send({ event: 'my-test-event', channel: 'my-test-channel', data: {} });
94
110
 
95
- server.send('{"event":"subscription_succeeded","channel":"my-test-channel"}')
111
+ expect(handler1).toHaveBeenCalledTimes(1);
112
+ expect(handler2).toHaveBeenCalledTimes(1);
113
+ });
96
114
 
97
- expect(channel).toBeInstanceOf(Channel)
115
+ test('stopListening with a callback only removes that callback', async () => {
116
+ connector = new Connector({ host: mockedHost });
117
+ await identify(server, 'test-socket-id');
98
118
 
99
119
  const handler1 = jest.fn();
100
120
  const handler2 = jest.fn();
101
121
 
102
- channel.on('client-whisper', handler1)
122
+ const channel = connector.channel('my-test-channel')
123
+ .listen('.my-test-event', handler1)
124
+ .listen('.my-test-event', handler2);
125
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'my-test-channel' } });
126
+
127
+ channel.stopListening('.my-test-event', handler1);
128
+ server.send({ event: 'my-test-event', channel: 'my-test-channel', data: {} });
129
+
130
+ expect(handler1).not.toHaveBeenCalled();
131
+ expect(handler2).toHaveBeenCalledTimes(1);
132
+ });
133
+
134
+ test('stopListening without a callback removes every listener of the event', async () => {
135
+ connector = new Connector({ host: mockedHost });
136
+ await identify(server, 'test-socket-id');
137
+
138
+ const handler = jest.fn();
103
139
 
104
- server.send('{"event":"client-whisper","data":"whisper","channel":"my-test-channel","data":{}}')
140
+ const channel = connector.channel('my-test-channel').listen('.my-test-event', handler);
141
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'my-test-channel' } });
105
142
 
106
- expect(handler1).toBeCalled();
107
- expect(handler2).not.toBeCalled();
108
- })
143
+ channel.stopListening('.my-test-event');
144
+ server.send({ event: 'my-test-event', channel: 'my-test-channel', data: {} });
145
+
146
+ expect(handler).not.toHaveBeenCalled();
147
+ });
148
+
149
+ test('channels joined after connecting are resubscribed after a reconnect', async () => {
150
+ connector = new Connector({ host: mockedHost, reconnectDelay: 10 });
151
+ await identify(server, 'test-socket-id');
152
+
153
+ const handler = jest.fn();
154
+ connector.channel('late-channel').listen('.my-test-event', handler);
155
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'late-channel' } });
156
+
157
+ server = await restartServer(server);
158
+ await identify(server, 'test-socket-id2');
159
+
160
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'late-channel' } });
161
+
162
+ server.send({ event: 'my-test-event', channel: 'late-channel', data: {} });
163
+ expect(handler).toHaveBeenCalledTimes(1);
164
+ });
165
+
166
+ test('channels that were left are not resubscribed after a reconnect', async () => {
167
+ connector = new Connector({ host: mockedHost, reconnectDelay: 10 });
168
+ connector.channel('left-channel');
169
+ connector.channel('kept-channel');
170
+
171
+ await identify(server, 'test-socket-id');
172
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'left-channel' } });
173
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'kept-channel' } });
174
+
175
+ connector.leave('left-channel');
176
+ await expect(server).toReceiveMessage({ event: 'unsubscribe', data: { channel: 'left-channel' } });
177
+
178
+ server = await restartServer(server);
179
+ await identify(server, 'test-socket-id2');
180
+
181
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'kept-channel' } });
182
+ await flushPromises();
183
+ expect(server.messages).not.toContainEqual({ event: 'subscribe', data: { channel: 'left-channel' } });
184
+ });
185
+
186
+ test('pings are not duplicated after reconnecting', async () => {
187
+ connector = new Connector({ host: mockedHost, reconnectDelay: 10, pingInterval: 40 });
188
+ await identify(server, 'test-socket-id');
189
+
190
+ server = await restartServer(server);
191
+ await identify(server, 'test-socket-id2');
192
+
193
+ await new Promise((resolve) => setTimeout(resolve, 210));
194
+
195
+ const pings = server.messages.filter((message: any) => message.event === 'ping');
196
+ expect(pings.length).toBeGreaterThanOrEqual(3);
197
+ expect(pings.length).toBeLessThanOrEqual(6);
198
+ });
199
+
200
+ test('subscribed callbacks run when the server confirms the subscription', async () => {
201
+ connector = new Connector({ host: mockedHost });
202
+ await identify(server, 'test-socket-id');
203
+
204
+ const subscribed = jest.fn();
205
+ connector.channel('my-test-channel').subscribed(subscribed);
206
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'my-test-channel' } });
207
+
208
+ server.send({ event: 'subscription_succeeded', channel: 'my-test-channel', data: [] });
209
+
210
+ expect(subscribed).toHaveBeenCalledTimes(1);
211
+ });
212
+
213
+ test('we can send a whisper event and listen for whispers', async () => {
214
+ connector = new Connector({ host: mockedHost });
215
+ mockFetchResponse({ auth: 'signature' });
216
+ await identify(server, 'test-socket-id');
217
+
218
+ const channel = connector.privateChannel('my-test-channel');
219
+ await expect(server).toReceiveMessage({
220
+ event: 'subscribe',
221
+ data: { channel: 'private-my-test-channel', auth: 'signature' },
222
+ });
223
+
224
+ const handler = jest.fn();
225
+ channel.listenForWhisper('typing', handler);
226
+ channel.whisper('typing', { name: 'Ana' });
227
+
228
+ await expect(server).toReceiveMessage({
229
+ event: 'client-typing',
230
+ channel: 'private-my-test-channel',
231
+ data: { name: 'Ana' },
232
+ });
233
+
234
+ server.send({ event: 'client-typing', channel: 'private-my-test-channel', data: { name: 'Luis' } });
235
+ expect(handler).toHaveBeenCalledWith({ name: 'Luis' });
236
+ });
237
+
238
+ describe('private channel authorization', () => {
239
+ test('posts to the auth endpoint with the configured headers', async () => {
240
+ const fetchMock = mockFetchResponse({ auth: 'signature' });
241
+
242
+ connector = new Connector({
243
+ host: mockedHost,
244
+ authEndpoint: 'https://app.test/broadcasting/auth',
245
+ bearerToken: 'secret-token',
246
+ auth: { headers: { 'X-Tenant': 'tenant-1' } },
247
+ });
248
+ connector.privateChannel('orders');
249
+
250
+ await identify(server, 'test-socket-id');
251
+
252
+ await expect(server).toReceiveMessage({
253
+ event: 'subscribe',
254
+ data: { channel: 'private-orders', auth: 'signature' },
255
+ });
256
+ expect(fetchMock).toHaveBeenCalledWith('https://app.test/broadcasting/auth', {
257
+ method: 'POST',
258
+ headers: {
259
+ 'Content-Type': 'application/json',
260
+ 'Accept': 'application/json',
261
+ 'Authorization': 'Bearer secret-token',
262
+ 'X-Tenant': 'tenant-1',
263
+ },
264
+ body: JSON.stringify({ socket_id: 'test-socket-id', channel_name: 'private-orders' }),
265
+ });
266
+ });
267
+
268
+ test('uses channelAuthorization endpoint and headers when given', async () => {
269
+ const fetchMock = mockFetchResponse({ auth: 'signature' });
270
+
271
+ connector = new Connector({
272
+ host: mockedHost,
273
+ channelAuthorization: {
274
+ endpoint: 'https://api.test/broadcasting/auth',
275
+ headers: { 'X-Api-Key': 'key' },
276
+ },
277
+ });
278
+ connector.privateChannel('orders');
279
+
280
+ await identify(server, 'test-socket-id');
281
+ await expect(server).toReceiveMessage({
282
+ event: 'subscribe',
283
+ data: { channel: 'private-orders', auth: 'signature' },
284
+ });
285
+
286
+ expect(fetchMock).toHaveBeenCalledWith('https://api.test/broadcasting/auth', expect.objectContaining({
287
+ headers: expect.objectContaining({ 'X-Api-Key': 'key' }),
288
+ }));
289
+ });
290
+
291
+ test('uses channelAuthorization.customHandler when given', async () => {
292
+ const fetchMock = mockFetchResponse({ auth: 'from-fetch' });
293
+ const customHandler = jest.fn((params, callback) => callback(null, { auth: 'from-handler' }));
294
+
295
+ connector = new Connector({ host: mockedHost, channelAuthorization: { customHandler } });
296
+ connector.privateChannel('orders');
297
+
298
+ await identify(server, 'test-socket-id');
299
+ await expect(server).toReceiveMessage({
300
+ event: 'subscribe',
301
+ data: { channel: 'private-orders', auth: 'from-handler' },
302
+ });
303
+
304
+ expect(customHandler).toHaveBeenCalledWith(
305
+ { socketId: 'test-socket-id', channelName: 'private-orders' },
306
+ expect.any(Function),
307
+ );
308
+ expect(fetchMock).not.toHaveBeenCalled();
309
+ });
310
+
311
+ test('reports a failed authorization to the channel error callbacks', async () => {
312
+ mockFetchResponse({ message: 'Forbidden' }, false, 403);
313
+
314
+ connector = new Connector({ host: mockedHost });
315
+ const onError = jest.fn();
316
+ connector.privateChannel('orders').error(onError);
317
+
318
+ await identify(server, 'test-socket-id');
319
+ await flushPromises();
320
+ await flushPromises();
321
+
322
+ expect(onError).toHaveBeenCalledWith(expect.objectContaining({ type: 'AuthError', status: 403 }));
323
+ expect(server.messages).not.toContainEqual(expect.objectContaining({ event: 'subscribe' }));
324
+ });
325
+
326
+ test('reports a rejected subscription to the channel error callbacks', async () => {
327
+ mockFetchResponse({ auth: 'bad-signature' });
328
+
329
+ connector = new Connector({ host: mockedHost });
330
+ const onError = jest.fn();
331
+ connector.privateChannel('orders').error(onError);
332
+
333
+ await identify(server, 'test-socket-id');
334
+ await expect(server).toReceiveMessage({
335
+ event: 'subscribe',
336
+ data: { channel: 'private-orders', auth: 'bad-signature' },
337
+ });
338
+
339
+ server.send({ event: 'error', channel: 'private-orders', data: { message: 'Invalid auth signature' } });
340
+
341
+ expect(onError).toHaveBeenCalledWith({ message: 'Invalid auth signature' });
342
+ });
343
+ });
109
344
  });
@@ -0,0 +1,96 @@
1
+ import WS from "jest-websocket-mock";
2
+ import EchoV2 from "laravel-echo";
3
+ import { Connector, broadcaster } from "../js-src/Connector";
4
+ import { identify, mockedHost, mockFetchResponse } from "./helpers";
5
+
6
+ // laravel-echo v1, installed under an alias. Its CommonJS build exports the class itself.
7
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
8
+ const echoV1Module = require("laravel-echo-v1");
9
+ const EchoV1 = echoV1Module.default ?? echoV1Module;
10
+
11
+ const echoVersions: Array<[string, any]> = [
12
+ ['laravel-echo v1', EchoV1],
13
+ ['laravel-echo v2', EchoV2],
14
+ ];
15
+
16
+ describe.each(echoVersions)('%s', (_version, Echo) => {
17
+ let server: WS;
18
+ let echo: any;
19
+
20
+ beforeEach(() => {
21
+ server = new WS(mockedHost, { jsonProtocol: true });
22
+ });
23
+
24
+ afterEach(() => {
25
+ echo?.disconnect();
26
+ echo = undefined;
27
+ WS.clean();
28
+ });
29
+
30
+ test.each([
31
+ ['Connector class', Connector],
32
+ ['broadcaster export', broadcaster],
33
+ ])('accepts the %s as broadcaster', async (_label, broadcasterOption) => {
34
+ echo = new Echo({ broadcaster: broadcasterOption, host: mockedHost });
35
+
36
+ await identify(server, 'socket-1');
37
+
38
+ expect(echo.connector).toBeInstanceOf(Connector);
39
+ expect(echo.socketId()).toBe('socket-1');
40
+ });
41
+
42
+ test('authorizes a private channel and delivers namespaced events', async () => {
43
+ const fetchMock = mockFetchResponse({ auth: 'signature' });
44
+
45
+ echo = new Echo({
46
+ broadcaster: Connector,
47
+ host: mockedHost,
48
+ authEndpoint: 'https://app.test/broadcasting/auth',
49
+ bearerToken: 'secret-token',
50
+ });
51
+
52
+ const handler = jest.fn();
53
+ echo.private('orders').listen('OrderCreated', handler);
54
+
55
+ await identify(server, 'socket-1');
56
+
57
+ await expect(server).toReceiveMessage({
58
+ event: 'subscribe',
59
+ data: { channel: 'private-orders', auth: 'signature' },
60
+ });
61
+
62
+ expect(fetchMock).toHaveBeenCalledWith('https://app.test/broadcasting/auth', expect.objectContaining({
63
+ method: 'POST',
64
+ headers: expect.objectContaining({ Authorization: 'Bearer secret-token' }),
65
+ body: JSON.stringify({ socket_id: 'socket-1', channel_name: 'private-orders' }),
66
+ }));
67
+
68
+ server.send({ event: 'App\\Events\\OrderCreated', channel: 'private-orders', data: { id: 1 } });
69
+
70
+ expect(handler).toHaveBeenCalledWith({ id: 1 });
71
+ });
72
+
73
+ test('leaving a channel unsubscribes from it', async () => {
74
+ echo = new Echo({ broadcaster: Connector, host: mockedHost });
75
+
76
+ echo.channel('news');
77
+ await identify(server, 'socket-1');
78
+ await expect(server).toReceiveMessage({ event: 'subscribe', data: { channel: 'news' } });
79
+
80
+ echo.leave('news');
81
+
82
+ await expect(server).toReceiveMessage({ event: 'unsubscribe', data: { channel: 'news' } });
83
+ });
84
+ });
85
+
86
+ describe('Connector', () => {
87
+ afterEach(() => WS.clean());
88
+
89
+ test('does not open a connection when constructed without options', () => {
90
+ // laravel-echo v2 probes custom broadcasters by calling `new broadcaster()` without arguments.
91
+ const server = new WS(mockedHost, { jsonProtocol: true });
92
+
93
+ expect(() => new Connector()).not.toThrow();
94
+ expect(server.server.clients()).toHaveLength(0);
95
+ });
96
+ });
@@ -0,0 +1,37 @@
1
+ import WS from "jest-websocket-mock";
2
+
3
+ export const mockedHost = 'ws://localhost:1234';
4
+
5
+ /**
6
+ * Wait for the client to connect and ask for its socket id, then answer with the given id.
7
+ */
8
+ export async function identify(server: WS, socketId: string): Promise<void> {
9
+ await server.connected;
10
+ await expect(server).toReceiveMessage({ event: 'whoami' });
11
+ server.send({ event: 'whoami', data: { socket_id: socketId } });
12
+ }
13
+
14
+ /**
15
+ * Close the current mock server and start a fresh one on the same host, simulating a dropped connection.
16
+ */
17
+ export async function restartServer(server: WS): Promise<WS> {
18
+ server.close();
19
+ await server.closed;
20
+ WS.clean();
21
+
22
+ return new WS(mockedHost, { jsonProtocol: true });
23
+ }
24
+
25
+ export function mockFetchResponse(body: object, ok = true, status = 200): jest.Mock {
26
+ const fetchMock = jest.fn().mockResolvedValue({
27
+ ok,
28
+ status,
29
+ json: () => Promise.resolve(body),
30
+ });
31
+
32
+ (globalThis as any).fetch = fetchMock;
33
+
34
+ return fetchMock;
35
+ }
36
+
37
+ export const flushPromises = (): Promise<void> => new Promise((resolve) => setTimeout(resolve, 0));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "laravel-echo-api-gateway",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Use Laravel Echo with API Gateway Websockets",
5
5
  "keywords": [
6
6
  "laravel",
@@ -21,46 +21,39 @@
21
21
  "license": "MIT",
22
22
  "main": "dist/laravel-echo-api-gateway.common.js",
23
23
  "module": "dist/laravel-echo-api-gateway.js",
24
- "types": "dist/laravel-echo-api-gateway.d.ts",
24
+ "types": "dist/Connector.d.ts",
25
25
  "scripts": {
26
26
  "build": "npm run compile && npm run declarations",
27
27
  "compile": "./node_modules/.bin/rollup -c",
28
28
  "declarations": "./node_modules/.bin/tsc --emitDeclarationOnly",
29
29
  "lint": "eslint --ext .js,.ts ./js-src ./js-tests",
30
- "prepublish": "npm run build",
31
30
  "release": "npm run test && standard-version && git push --follow-tags && npm publish",
32
- "test": "jest"
31
+ "test": "jest",
32
+ "prepare": "npm run build"
33
33
  },
34
34
  "devDependencies": {
35
- "@babel/plugin-proposal-decorators": "^7.8.3",
36
- "@babel/plugin-proposal-export-namespace-from": "^7.8.3",
37
- "@babel/plugin-proposal-function-sent": "^7.8.3",
38
- "@babel/plugin-proposal-numeric-separator": "^7.8.3",
39
- "@babel/plugin-proposal-throw-expressions": "^7.8.3",
40
- "@babel/plugin-transform-object-assign": "^7.8.3",
41
- "@babel/preset-env": "^7.9.6",
42
- "@rollup/plugin-babel": "^5.0.0",
43
- "@types/babel__traverse": "^7.20.6",
44
- "@types/jest": "^24.0.18",
45
- "@types/node": "^12.7.5",
46
- "@typescript-eslint/eslint-plugin": "^3.7.0",
47
- "@typescript-eslint/parser": "^3.7.0",
35
+ "@rollup/plugin-typescript": "^12.3.0",
36
+ "@types/jest": "^29.5.14",
37
+ "@types/node": "^20.19.43",
38
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
39
+ "@typescript-eslint/parser": "^5.62.0",
48
40
  "eslint": "^7.5.0",
49
- "jest": "^24.9.0",
50
- "jest-websocket-mock": "^2.2.0",
51
- "laravel-echo": "1.10.0",
52
- "mock-socket": "^9.0.3",
53
- "rollup": "^2.10.2",
54
- "rollup-plugin-commonjs": "^10.1.0",
55
- "rollup-plugin-json": "^4.0.0",
56
- "rollup-plugin-node-resolve": "^5.2.0",
57
- "rollup-plugin-typescript2": "^0.27.1",
41
+ "jest": "^29.7.0",
42
+ "jest-environment-jsdom": "^29.7.0",
43
+ "jest-websocket-mock": "^2.5.0",
44
+ "laravel-echo": "^2.5.0",
45
+ "laravel-echo-v1": "npm:laravel-echo@^1.10.0",
46
+ "mock-socket": "^9.3.1",
47
+ "rollup": "^4.64.0",
58
48
  "standard-version": "^8.0.1",
59
- "ts-jest": "^24.1.0",
60
- "tslib": "^1.10.0",
61
- "typescript": "^5.7.2"
49
+ "ts-jest": "^29.4.14",
50
+ "tslib": "^2.8.1",
51
+ "typescript": "^5.9.3"
62
52
  },
63
53
  "engines": {
64
- "node": ">=10"
54
+ "node": ">=18"
55
+ },
56
+ "peerDependencies": {
57
+ "laravel-echo": "^1.10.0 || ^2.0.0"
65
58
  }
66
59
  }
package/phpstan.neon.dist CHANGED
@@ -1,21 +1,12 @@
1
1
  includes:
2
- - ./vendor/nunomaduro/larastan/extension.neon
2
+ - ./vendor/larastan/larastan/extension.neon
3
3
 
4
4
  parameters:
5
5
 
6
- phpVersion: 80399
7
-
8
6
  paths:
9
7
  - src
10
- - tests
11
8
 
12
- level: max
9
+ level: 6
13
10
 
14
11
  ignoreErrors:
15
- - '#^Cannot call method debug\(\) on Illuminate\\Log\\LogManager\|null.$#'
16
- - '#^Call to an undefined method Mockery\\ExpectationInterface\|Mockery\\HigherOrderMessage::withArgs\(\).$#'
17
- #
18
- # excludePaths:
19
- # - ./*/*/FileToBeExcluded.php
20
-
21
- checkMissingIterableValueType: false
12
+ - identifier: missingType.iterableValue
package/phpunit.xml CHANGED
@@ -9,9 +9,9 @@
9
9
  <directory suffix="Test.php">./tests</directory>
10
10
  </testsuite>
11
11
  </testsuites>
12
- <coverage processUncoveredFiles="true">
12
+ <source>
13
13
  <include>
14
14
  <directory suffix=".php">./src</directory>
15
15
  </include>
16
- </coverage>
16
+ </source>
17
17
  </phpunit>