Skip to content

Commit

Permalink
Merge branch 'Adesin-fr-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
leob committed Nov 14, 2024
2 parents f5e65ed + 9d623ef commit a120008
Show file tree
Hide file tree
Showing 6 changed files with 5,374 additions and 5,339 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ advised to only use this package for non-critical / non-production projects.
In order to use this package, your project needs to meet the following criteria:

- PHP 7.4 or 8.x
- Laravel 6, 7 or 8
- Laravel 6 to 11
- Uses either [bref](https://bref.sh) or [Laravel Vapor](https://vapor.laravel.com) to deploy to AWS
- Has a working queue
- Uses Laravel Mix or any other tool to bundle your assets
Expand Down Expand Up @@ -120,6 +120,7 @@ provider:
environment:
# Add these variables
# Please note : in Laravel 11, this setting is now BROADCAST_CONNECTION
BROADCAST_DRIVER: laravel-echo-api-gateway
LARAVEL_ECHO_API_GATEWAY_DYNAMODB_TABLE: !Ref ConnectionsTable
LARAVEL_ECHO_API_GATEWAY_API_ID: !Ref WebsocketsApi
Expand Down Expand Up @@ -201,4 +202,19 @@ window.Echo = new Echo({
});
```

You can also enable console output by passing a `debug: true` otpion to your window.Echo intializer :
```js
import Echo from 'laravel-echo';
import {broadcaster} from 'laravel-echo-api-gateway';
window.Echo = new Echo({
broadcaster,
// replace the placeholders
host: 'wss://{api-ip}.execute-api.{region}.amazonaws.com/{stage}',
debug: true
});
```



Lastly, you have to generate your assets by running Laravel Mix. After this step, you should be up and running.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"php": "^8.0|^8.1|^8.2",
"ext-json": "*",
"aws/aws-sdk-php": "^3.308",
"bref/bref": "^1.1",
"bref/bref": "^1.1|^2.0",
"guzzlehttp/guzzle": "^6.3|^7.0",
"laravel/framework": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0"
},
Expand Down
74 changes: 50 additions & 24 deletions js-src/Websocket.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {Channel} from "./Channel";
import {AxiosResponse} from "axios";
import { AxiosResponse } from "axios";
import axios from 'axios';
import { Channel } from "./Channel";

export type Options = { authEndpoint: string, host: string, bearerToken: string, auth: any, debug: boolean };

export type Options = { authEndpoint: string, host: string, bearerToken: string, auth: any };
export type MessageBody = { event: string, channel?: string, data: object };

export class Websocket {
Expand All @@ -19,14 +21,20 @@ export class Websocket {

private socketId: string;

private closing = false;

private pingInterval: NodeJS.Timeout;

constructor(options: Options) {
this.options = options;
private connect(host: string): void {
this.options.debug && console.log('Connecting');

this.websocket = new WebSocket(options.host)
this.websocket = new WebSocket(host)

this.websocket.onopen = () => {
this.send({
event: 'whoami',
})

while (this.buffer.length) {
const message = this.buffer[0]

Expand All @@ -44,7 +52,7 @@ export class Websocket {
}

if (message.channel) {
console.log(`Received event ${message.event} on channel ${message.channel}`)
this.options.debug && console.log(`Received event ${message.event} on channel ${message.channel}`)

if (this.listeners[message.channel] && this.listeners[message.channel][message.event]) {
this.listeners[message.channel][message.event](message.data)
Expand All @@ -56,12 +64,24 @@ export class Websocket {
if (this.internalListeners[message.event]) {
this.internalListeners[message.event](message.data)
}

}


this.websocket.onclose = () => {
if (this.socketId && !this.closing || !this.socketId) {
this.options.debug && console.info('Connection lost, reconnecting...');
setTimeout(() => {
this.socketId = undefined
this.connect(host)
}, 1000);
}
};

this.on('whoami', ({ socket_id: socketId }) => {
this.socketId = socketId

console.log(`just set socketId to ${socketId}`)
this.options.debug && console.log(`just set socketId to ${socketId}`)

while (this.channelBacklog.length) {
const channel = this.channelBacklog[0]
Expand All @@ -72,27 +92,32 @@ export class Websocket {
}
})

this.send({
event: 'whoami',
})

// send ping every 60 seconds to keep connection alive
this.pingInterval = setInterval(() => {
console.log('Sending ping')

this.send({
event: 'ping',
})
if (this.websocket.readyState === this.websocket.OPEN) {
this.options.debug && console.log('Sending ping')
this.send({
event: 'ping',
})
}
}, 60 * 1000)

}

constructor(options: Options) {
this.options = options;

this.connect(this.options.host);

return this
}

protected parseMessage(body: string): MessageBody {
try {
return JSON.parse(body)
} catch (error) {
console.error(error)
this.options.debug && console.error(error)

return undefined
}
Expand All @@ -115,7 +140,8 @@ export class Websocket {
this.buffer.push(message)
}

close (): void {
close(): void {
this.closing = true
this.internalListeners = {}

clearInterval(this.pingInterval)
Expand All @@ -134,7 +160,7 @@ export class Websocket {

private actuallySubscribe(channel: Channel): void {
if (channel.name.startsWith('private-') || channel.name.startsWith('presence-')) {
console.log(`Sending auth request for channel ${channel.name}`)
this.options.debug && console.log(`Sending auth request for channel ${channel.name}`)

if (this.options.bearerToken) {
this.options.auth.headers['Authorization'] = 'Bearer ' + this.options.bearerToken;
Expand All @@ -146,21 +172,21 @@ export class Websocket {
}, {
headers: this.options.auth.headers || {}
}).then((response: AxiosResponse) => {
console.log(`Subscribing to channels ${channel.name}`)
this.options.debug && console.log(`Subscribing to channels ${channel.name}`)

this.send({
event: 'subscribe',
data: {
channel: channel.name,
... response.data
...response.data
},
})
}).catch((error) => {
console.log(`Auth request for channel ${channel.name} failed`)
console.error(error)
this.options.debug && console.log(`Auth request for channel ${channel.name} failed`)
this.options.debug && console.error(error)
})
} else {
console.log(`Subscribing to channels ${channel.name}`)
this.options.debug && console.log(`Subscribing to channels ${channel.name}`)

this.send({
event: 'subscribe',
Expand Down
31 changes: 27 additions & 4 deletions js-tests/Connector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import WS from "jest-websocket-mock";
import { Connector } from "../js-src/Connector";
import { Channel } from "../js-src/Channel";

const mockedHost = 'ws://localhost:1234';

describe('Connector', () => {
let server: WS;

beforeEach(() => {
server = new WS("ws://localhost:1234");
jest.useRealTimers();
server = new WS(mockedHost);
});

afterEach(() => {
Expand All @@ -15,7 +18,7 @@ describe('Connector', () => {

test('socket id is correctly set', async () => {
const connector = new Connector({
host: "ws://localhost:1234",
host: mockedHost,
})

await server.connected;
Expand All @@ -26,9 +29,29 @@ describe('Connector', () => {
expect(connector.socketId()).toBe('test-socket-id')
})

test('we reconnect to the server on error', async () => {
const connector = new Connector({
host: mockedHost,
})

await server.connected;
await expect(server).toReceiveMessage('{"event":"whoami"}');
server.send('{"event":"whoami","data":{"socket_id":"test-socket-id"}}')

server.close();
await server.closed;
server.server.stop(() => (server = new WS(mockedHost)));

await server.connected;
await expect(server).toReceiveMessage('{"event":"whoami"}');
server.send('{"event":"whoami","data":{"socket_id":"test-socket-id2"}}')

expect(connector.socketId()).toBe('test-socket-id2')
})

test('we can subscribe to a channel and listen to events', async () => {
const connector = new Connector({
host: "ws://localhost:1234",
host: mockedHost,
})

await server.connected;
Expand Down Expand Up @@ -57,7 +80,7 @@ describe('Connector', () => {

test('we can send a whisper event', async () => {
const connector = new Connector({
host: "ws://localhost:1234",
host: mockedHost,
})

await server.connected;
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
"jest": "^24.9.0",
"jest-websocket-mock": "^2.2.0",
"laravel-echo": "^1.10.0",
"mock-socket": "^9.0.3",
"rollup": "^2.10.2",
"rollup-plugin-typescript2": "^0.27.1",
"standard-version": "^8.0.1",
Expand Down
Loading

0 comments on commit a120008

Please sign in to comment.