https://github.com/tw00/graphql-websocket-router
GraphQL-WebSocket-Router
https://github.com/tw00/graphql-websocket-router
Last synced: 22 days ago
JSON representation
GraphQL-WebSocket-Router
- Host: GitHub
- URL: https://github.com/tw00/graphql-websocket-router
- Owner: tw00
- Created: 2021-11-29T12:10:42.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2021-12-05T03:29:26.000Z (over 3 years ago)
- Last Synced: 2025-02-17T20:19:36.485Z (4 months ago)
- Language: TypeScript
- Size: 150 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# GraphQL WebSocket Router
GraphQL WebSocket Router allows you to expose an internal GraphQL API over Websocket without exposing the entire schema.
# Getting started
GraphQL Rest Router is available via NPM as `graphql-websocket-router`
```bash
npm install --save graphql-websocket-router
```## Queries (`queries.gql`)
```gql
# GraphQL Subscription
subscription OnEvent($topic: String) {
onEvent(topic: $topic) {
timestamp
message
}
}# GraphQL Live Query
query GetEpisodeById($id: ID!) {
episode(id: $id) @live {
id
name
air_date
}
}
```## Setting up the router/gateway with uWebSockets
```ts
import GraphQLWebsocketRouter from "graphql-websocket-router";
import { App as uWebSocketApp } from "uWebSockets.js";
import { readFileSync } from "fs";
import { resolve } from "path";const api = new GraphQLWebsocketRouter(
"ws://localhost:4000/graphql",
readFileSync(resolve(__dirname, "queries.gql"), "utf-8")
);uWebSocketApp()
.ws("/*", api.uWebSocketBehavior())
.listen(9001, (listenSocket) => {
if (listenSocket) {
console.log("Listening on port 9001");
}
});
```## WebSocket Protocol
```js
// Example: Query
>> { method: "query", operation: "GetEpisodeById", variables: { id: 1 } }
<< { status: "ok", data: { id: 1, name: "Episode One" } }// Example: Subscription
>> { method: "subscribe", operation: "OnEvent", variables: { topic: 'all' } }
<< { status: "ok", data: { timestamp: 1, message: "hello" } }
<< { status: "update", data: { timestamp: 2, message: "world" } }
<< { status: "update", data: { timestamp: 3, message: "!" } }// Example: Live Subscribe
>> { method: "subscribe", operation: "GetEpisodeById", variables: { id: 1 } }
<< { status: "ok", data: { id: 1, name: "Episode O" } }
<< { status: "update", data: { name: "Episode On" } }
<< { status: "update", data: { name: "Episode One" } }// Example: Unsubscribe
>> { method: "unsubscribe", operation: "GetEpisodeById", variables: { id: 1 } }
<< { status: "ok" }// Example: Error
>> { method: "query", operation: "GetEpisodeById", /* missing id */ }
<< { status: "error", error: { message: "id is missing" } }
```# Supported backends
## Connecting to WebSocket backend
Supports **live queries**, **subscriptions**, **queries** and **mutations**.
```ts
// ...const api = new GraphQLWebsocketRouter(
"ws://localhost:4000/graphql",
readFileSync(resolve(__dirname, "queries.gql"), "utf-8"),
{ enableDeltaPatching: false }
);// ...
```## Connecting to HTTP backend
Supports **queries** and **mutations** only.
```ts
// ...const api = new GraphQLWebsocketRouter(
"https://rickandmortyapi.com/graphql",
readFileSync(resolve(__dirname, "queries.gql"), "utf-8")
);// ...
```# Client Examples
## Vanilla
```ts
const socket = new WebSocket("ws://localhost:9001");socket.onopen = (event) => {
// connection established
socket.send(
JSON.stringify({
method: "subscribe",
operation: "GetEpisodeById",
variables: { id: 1 },
})
);
};socket.onmessage = (event) => {
const { status, data: document } = JSON.parse(event.data);
console.log("[received]", document);
};socket.onerror = (error) => {
// handle error
};
```## React Hook (TBD)
```ts
import { useLiveQuery } from "graphql-websocket-router/client/react";export default function MyComponent() {
const document = useLiveQuery({
operation: "GetEpisodeById",
variables: { id: 1 },
});return
{JSON.stringify(document)};
}
```## Next.js (TBD)
```ts
import {
fetchLiveQuery,
useLiveQuery,
} from "graphql-websocket-router/client/react";export async function getStaticProps(context) {
const { query: episodeQuery } = await fetchLiveQuery({
operation: "GetEpisodeById",
variables: { id: 1 },
});return {
props: { episodeQuery },
};
}export default function EpisodeDetails({ episodeQuery }) {
const episode = useLiveQuery(episodeQuery);// Render episode...
}
```