-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BREAKING CHANGE: the subscription server export is now an abstract class
- Loading branch information
Showing
17 changed files
with
800 additions
and
196 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,36 @@ | ||
# GraphQL Subscription Server | ||
|
||
A subscription server for GraphQL subscriptions. Supports streaming over plain web sockets | ||
or Socket.IO, and integrates with Redis or any other Pub/Sub service. | ||
|
||
## Setup | ||
|
||
### Socket.IO | ||
|
||
```js | ||
import http from 'http'; | ||
import { | ||
SocketIOSubscriptionServer, // or WebSocketSubscriptionServer | ||
JwtCredentialManager, | ||
RedisSubscriber, | ||
} from '@4c/graphql-subscription-server'; | ||
|
||
const server = http.createServer(); | ||
|
||
const subscriptionServer = new SocketIOSubscriptionServer({ | ||
schema, | ||
path: '/socket.io/graphql', | ||
subscriber: new RedisSubscriber(), | ||
hasPermission: (message, credentials) => { | ||
authorize(message, credentials); | ||
}, | ||
createCredentialsManager: (req) => new JwtCredentialManager(), | ||
createLogger: () => console.debug, | ||
}); | ||
|
||
subscriptionServer.attach(server); | ||
|
||
server.listen(4000, () => { | ||
console.log('server running'); | ||
}); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { promisify } from 'util'; | ||
|
||
import express from 'express'; | ||
import type io from 'socket.io'; | ||
|
||
import SubscriptionServer, { | ||
SubscriptionServerConfig, | ||
} from './SubscriptionServer'; | ||
|
||
export interface SocketIOSubscriptionServerConfig<TContext, TCredentials> | ||
extends SubscriptionServerConfig<TContext, TCredentials> { | ||
socketIoServer?: io.Server; | ||
} | ||
|
||
export default class SocketIOSubscriptionServer< | ||
TContext, | ||
TCredentials, | ||
> extends SubscriptionServer<TContext, TCredentials> { | ||
io: io.Server; | ||
|
||
constructor({ | ||
socketIoServer, | ||
...config | ||
}: SocketIOSubscriptionServerConfig<TContext, TCredentials>) { | ||
super(config); | ||
|
||
this.io = socketIoServer!; | ||
if (!this.io) { | ||
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires | ||
const IoServer = require('socket.io').Server; | ||
this.io = new IoServer({ | ||
serveClient: false, | ||
path: this.config.path, | ||
transports: ['websocket'], | ||
allowEIO3: true, | ||
}); | ||
} | ||
|
||
this.io.on('connection', (socket: io.Socket) => { | ||
const clientId = socket.id; | ||
|
||
const request = Object.create((express as any).request); | ||
Object.assign(request, socket.request); | ||
|
||
this.log('debug', 'SubscriptionServer: new socket connection', { | ||
clientId, | ||
numClients: this.io.engine?.clientsCount ?? 0, | ||
}); | ||
|
||
this.opened( | ||
{ | ||
id: clientId, | ||
protocol: 'socket-io', | ||
on: socket.on.bind(socket), | ||
emit(event: string, data: any) { | ||
socket.emit(event, data); | ||
}, | ||
close() { | ||
socket.disconnect(); | ||
}, | ||
}, | ||
request, | ||
); | ||
|
||
// add after so the logs happen in order | ||
socket.once('disconnect', (reason) => { | ||
this.log('debug', 'socket disconnected', { | ||
reason, | ||
clientId, | ||
numClients: (this.io.engine.clientsCount ?? 0) - 1, // number hasn't decremented at this point for this client | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
attach(httpServer: any) { | ||
this.io.attach(httpServer); | ||
} | ||
|
||
async close() { | ||
// @ts-ignore | ||
await promisify((...args) => this.io.close(...args))(); | ||
} | ||
} |
Oops, something went wrong.