![Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility](https://cdn.sanity.io/images/cgdhsj6q/production/97774ea8c88cc8f4bed2766c31994ebc38116948-1664x1366.png?w=400&fit=max&auto=format)
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
graphql-ws
Advanced tools
The graphql-ws package is a lightweight and fast WebSocket server and client for GraphQL subscriptions, designed to work with the GraphQL JavaScript reference implementation. It allows you to set up a full-duplex communication channel between the client and server to facilitate real-time data exchange using the GraphQL protocol.
Creating a WebSocket server for GraphQL subscriptions
This code sample demonstrates how to create a WebSocket server that handles GraphQL subscriptions. It uses the `useServer` function from `graphql-ws` to attach the WebSocket server to an existing HTTP server.
const { createServer } = require('http');
const { execute, subscribe } = require('graphql');
const { useServer } = require('graphql-ws/lib/use/ws');
const { schema } = require('./my-graphql-schema');
const server = createServer(function weServeSocketsOnly(_, res) {
res.writeHead(404);
res.end();
});
const wsServer = new WebSocket.Server({
server,
path: '/graphql',
});
useServer({ schema, execute, subscribe }, wsServer);
server.listen(4000);
Creating a WebSocket client for GraphQL subscriptions
This code sample shows how to create a WebSocket client that can subscribe to GraphQL subscriptions. The `createClient` function from `graphql-ws` is used to establish a connection to the WebSocket server, and the `subscribe` method is used to listen for real-time data updates.
const { createClient } = require('graphql-ws');
const client = createClient({
url: 'ws://localhost:4000/graphql',
});
client.subscribe(
{
query: 'subscription { somethingChanged { id } }',
variables: {},
},
{
next: data => console.log('data received:', data),
error: err => console.error('error during subscription:', err),
complete: () => console.log('subscription completed'),
}
);
This package is another implementation of GraphQL over WebSocket protocol. It is the predecessor of graphql-ws and was developed by the Apollo team. However, it is now deprecated in favor of graphql-ws, which is more lightweight and has a simpler API.
Apollo Server is a community-driven, open-source GraphQL server that works with many Node.js HTTP server frameworks. Apollo Server supports subscriptions with WebSocket and integrates well with the Apollo ecosystem. It is more feature-rich but also heavier compared to graphql-ws, which is focused solely on WebSocket communication.
(Work in progress!)
fork of subscriptions-transport-ws which adds file transfer over websocket.
A GraphQL WebSocket server and client to facilitate GraphQL queries, mutations and subscriptions over WebSocket.
See GitHunt-API and GitHunt-React for an example server and client integration.
Start by installing the package, using NPM.
Using NPM:
$ npm install --save graphql-ws
Note that you need to use this package on both GraphQL client and server.
Starting with the server, create a new simple PubSub
instance. We will later use this PubSub
to publish and subscribe to data changes.
import { PubSub } from 'graphql-subscriptions';
export const pubsub = new PubSub();
Now, create SubscriptionServer
instance, with your GraphQL schema
, execute
and subscribe
(from graphql-js
package):
import { createServer } from 'http';
import { SubscriptionServer } from 'graphql-ws';
import { execute, subscribe } from 'graphql';
import { schema } from './my-schema';
const WS_PORT = 5000;
// Create WebSocket listener server
const websocketServer = createServer((request, response) => {
response.writeHead(404);
response.end();
});
// Bind it to port and start listening
websocketServer.listen(WS_PORT, () => console.log(
`Websocket Server is now running on http://localhost:${WS_PORT}`
));
const subscriptionServer = SubscriptionServer.create(
{
schema,
execute,
subscribe,
},
{
server: websocketServer,
path: '/graphql',
},
);
Please refer to graphql-subscriptions
documentation for how to create your GraphQL subscriptions, and how to publish data.
When using this package for client side, you can choose either use HTTP request for Queries and Mutation and use the WebSocket for subscriptions only, or create a full transport that handles all type of GraphQL operations over the socket.
To start with a full WebSocket transport, that handles all types of GraphQL operations, import and create an instance of SubscriptionClient
.
Then, create your ApolloClient
instance and use the SubscriptionsClient
instance as network interface:
import { SubscriptionClient } from 'graphql-ws';
import ApolloClient from 'apollo-client';
const GRAPHQL_ENDPOINT = 'ws://localhost:3000/graphql';
const client = new SubscriptionClient(GRAPHQL_ENDPOINT, {
reconnect: true,
});
const apolloClient = new ApolloClient({
networkInterface: client,
});
Now, when you want to use subscriptions in client side, use your ApolloClient
instance, with subscribe
or query
subscribeToMore
:
apolloClient.subscribe({
query: gql`
subscription onNewItem {
newItemCreated {
id
}
}`,
variables: {}
}).subscribe({
next (data) {
// Notify your application with the new arrived data
}
});
apolloClient.query({
query: ITEM_LIST_QUERY,
variables: {}
}).subscribeToMore({
document: gql`
subscription onNewItem {
newItemCreated {
id
}
}`,
variables: {},
updateQuery: (prev, { subscriptionData, variables }) => {
// Perform updates on previousResult with subscriptionData
return updatedResult;
}
});
If you don't use any package/modules loader, you can still use this package, by using unpkg
service, and get the client side package from:
https://unpkg.com/graphql-ws@VERSION/browser/client.js
Replace VERSION with the latest version of the package.
You can use this package's power with GraphiQL, and subscribe to live-data stream inside GraphiQL.
If you are using the latest version of graphql-server
flavors (graphql-server-express
, graphql-server-koa
, etc...), you already can use it! Make sure to specify subscriptionsEndpoint
in GraphiQL configuration, and that's it!
For example, graphql-server-express
users need to add the following:
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: `YOUR_SUBSCRIPTION_ENDPOINT_HERE`,
}));
If you are using older version, or another GraphQL server, start by modifying GraphiQL static HTML, and add this package and it's fetcher from CDN:
<script src="//unpkg.com/graphql-ws@0.1.0/browser/client.js"></script>
<script src="//unpkg.com/graphiql-ws@0.1.0/browser/client.js"></script>
Then, create SubscriptionClient
and define the fetcher:
let subscriptionsClient = new window.GraphQLWS.SubscriptionClient('SUBSCRIPTION_WS_URL_HERE', {
reconnect: true
});
let myCustomFetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLFetcher);
graphQLFetcher
is the default fetcher, and we use it as fallback for non-subscription GraphQL operations.
And replace your GraphiQL creation logic to use the new fetcher:
ReactDOM.render(
React.createElement(GraphiQL, {
fetcher: myCustomFetcher, // <-- here
onEditQuery: onEditQuery,
onEditVariables: onEditVariables,
onEditOperationName: onEditOperationName,
query: ${safeSerialize(queryString)},
response: ${safeSerialize(resultString)},
variables: ${safeSerialize(variablesString)},
operationName: ${safeSerialize(operationName)},
}),
document.body
);
Constructor(url, options, connectionCallback)
url: string
: url that the client will connect to, starts with ws://
or wss://
options?: Object
: optional, object to modify default client behavior
timeout?: number
: how long the client should wait in ms for a keep-alive message from the server (default 10000 ms), this parameter is ignored if the server does not send keep-alive messages. This will also be used to calculate the max connection time per connect/reconnectlazy?: boolean
: use to set lazy mode - connects only when first subscription created, and delay the socket initializationconnectionParams?: Object | Function
: object that will be available as first argument of onConnect
(in server side), if passed a function - it will call it and send the return valuereconnect?: boolean
: automatic reconnect in case of connection errorreconnectionAttempts?: number
: how much reconnect attemptsconnectionCallback?: (error) => {}
: optional, callback that called after the first init message, with the error (if there is one)webSocketImpl?: Object
- optional, WebSocket implementation. use this when your environment does not have a built-in native WebSocket (for example, with NodeJS client)request(options) => Observable<ExecutionResult>
: returns observable to execute the operation.options: {OperationOptions}
query: string
: GraphQL subscriptionvariables: Object
: GraphQL subscription variablesoperationName: string
: operation name of the subscriptioncontext: Object
: use to override context for a specific callunsubscribeAll() => void
- unsubscribes from all active subscriptions.on(eventName, callback, thisContext) => Function
eventName: string
: the name of the event, available events are: connecting
, connected
, reconnecting
, reconnected
and disconnected
callback: Function
: function to be called when websocket connects and initialized.thisContext: any
: this
context to use when calling the callback function.off
method to cancel the event subscription.onConnected(callback, thisContext) => Function
- shorthand for .on('connected', ...)
callback: Function
: function to be called when websocket connects and initialized, after ACK message returned from the serverthisContext: any
: this
context to use when calling the callback function.off
method to cancel the event subscription.onReconnected(callback, thisContext) => Function
- shorthand for .on('reconnected', ...)
callback: Function
: function to be called when websocket reconnects and initialized, after ACK message returned from the serverthisContext: any
: this
context to use when calling the callback function.off
method to cancel the event subscription.onConnecting(callback, thisContext) => Function
- shorthand for .on('connecting', ...)
callback: Function
: function to be called when websocket starts it's connectionthisContext: any
: this
context to use when calling the callback function.off
method to cancel the event subscription.onReconnecting(callback, thisContext) => Function
- shorthand for .on('reconnecting', ...)
callback: Function
: function to be called when websocket starts it's reconnectionthisContext: any
: this
context to use when calling the callback function.off
method to cancel the event subscription.onDisconnected(callback, thisContext) => Function
- shorthand for .on('disconnected', ...)
callback: Function
: function to be called when websocket disconnected.thisContext: any
: this
context to use when calling the callback function.off
method to cancel the event subscription.close() => void
- closes the WebSocket connection manually, and ignores reconnect
logic if it was set to true
.use(middlewares: MiddlewareInterface[]) => SubscriptionClient
- adds middleware to modify OperationOptions
per each requestmiddlewares: MiddlewareInterface[]
- Array contains list of middlewares (implemented applyMiddleware
method) implementation, the SubscriptionClient
will use the middlewares to modify OperationOptions
for every operationstatus: number
: returns the current socket's readyState
Constructor(options, socketOptions)
options: {ServerOptions}
rootValue?: any
: Root value to use when executing GraphQL root operationsschema?: GraphQLSchema
: GraphQL schema objectexecute?: (schema, document, rootValue, contextValue, variableValues, operationName) => Promise<ExecutionResult> | AsyncIterator<ExecutionResult>
: GraphQL execute
function, provide the default one from graphql
package. Return value of AsyncItrator
is also valid since this package also support reactive execute
methods.subscribe?: (schema, document, rootValue, contextValue, variableValues, operationName) => Promise<ExecutionResult | AsyncIterator<ExecutionResult>>
: GraphQL subscribe
function, provide the default one from graphql
package.onOperation?: (message: SubscribeMessage, params: SubscriptionOptions, webSocket: WebSocket)
: optional method to create custom params that will be used when resolving this operationonOperationComplete?: (webSocket: WebSocket, opId: string)
: optional method that called when a GraphQL operation is done (for query and mutation it's immeditaly, and for subscriptions when unsubscribing)onConnect?: (connectionParams: Object, webSocket: WebSocket)
: optional method that called when a client connects to the socket, called with the connectionParams
from the client, if the return value is an object, its elements will be added to the context. return false
or throw an exception to reject the connection. May return a Promise.onDisconnect?: (webSocket: WebSocket)
: optional method that called when a client disconnectskeepAlive?: number
: optional interval in ms to send KEEPALIVE
messages to all clientssocketOptions: {WebSocket.IServerOptions}
: options to pass to the WebSocket object (full docs here)
server?: HttpServer
- existing HTTP server to use (use without host
/port
)
host?: string
- server host
port?: number
- server port
path?: string
- endpoint path
AsyncIterator
internally using iterall, for more information click here, or the proposalFAQs
Coherent, zero-dependency, lazy, simple, GraphQL over WebSocket Protocol compliant server and client
The npm package graphql-ws receives a total of 2,979,018 weekly downloads. As such, graphql-ws popularity was classified as popular.
We found that graphql-ws demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.