subscription-client v0.9.15
subscription-client
A GraphQL WebSocket client to facilitate GraphQL queries, mutations and subscriptions over WebSocket.
subscription-clientis an extension for GraphQL, and you can use it with any GraphQL client (not only Apollo).
Getting Started
Start by installing the package, using Yarn or NPM.
Using Yarn:
$ yarn add subscription-client
Or, using NPM:
$ npm install --save subscription-clientThis command also installs this package's dependencies, including
graphql-subscriptions.
Client
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.
Full WebSocket Transport
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 'subscription-client';
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,
});Hybrid WebSocket Transport
To start with a hybrid WebSocket transport, that handles only subscriptions over WebSocket, create your SubscriptionClient and a regular HTTP network interface, then extend your network interface to use the WebSocket client for GraphQL subscriptions:
import {SubscriptionClient, addGraphQLSubscriptions} from 'subscription-client';
import ApolloClient, {createNetworkInterface} from 'apollo-client';
// Create regular NetworkInterface by using apollo-client's API:
const networkInterface = createNetworkInterface({
uri: 'http://localhost:3000' // Your GraphQL endpoint
});
// Create WebSocket client
const wsClient = new SubscriptionClient(`ws://localhost:5000/`, {
reconnect: true,
connectionParams: {
// Pass any arguments you want for initialization
}
});
// Extend the network interface with the WebSocket
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
networkInterface,
wsClient
);
// Finally, create your ApolloClient instance with the modified network interface
const apolloClient = new ApolloClient({
networkInterface: networkInterfaceWithSubscriptions
});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/subscription-client@VERSION/browser/client.jsReplace VERSION with the latest version of the package.
Use it with GraphiQL
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/subscription-client@0.5.4/browser/client.js"></script>
<script src="//unpkg.com/graphiql-subscriptions-fetcher@0.0.2/browser/client.js"></script>Then, create SubscriptionClient and define the fetcher:
let subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient('SUBSCRIPTION_WS_URL_HERE', {
reconnect: true
});
let myCustomFetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLFetcher);
graphQLFetcheris 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
);API Docs
SubscriptionClient
Constructor(url, options, webSocketImpl)
url: string: url that the client will connect to, starts withws://orwss://options?: Object: optional, object to modify default client behaviortimeout?: number: how long the client should wait in ms for a keep-alive message from the server (default 30000 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 | Promise<Object>: object that will be available as first argument ofonConnect(in server side), if passed a function - it will call it and send the return value, if function returns as promise - it will wait until it resolves and send the resolved value.reconnect?: 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)inactivityTimeout?: number: how long the client should wait in ms, when there are no active subscriptions, before disconnecting from the server. Set to 0 to disable this behavior. (default 0)
webSocketImpl?: Object- optional, constructor for W3C compliant WebSocket implementation. Use this when your environment does not have a built-in native WebSocket (for example, with NodeJS client)
Methods
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 call
unsubscribeAll() => 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,disconnectedanderrorcallback: Function: function to be called when websocket connects and initialized.thisContext: any:thiscontext to use when calling the callback function.- => Returns an
offmethod 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:thiscontext to use when calling the callback function.- => Returns an
offmethod 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:thiscontext to use when calling the callback function.- => Returns an
offmethod 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:thiscontext to use when calling the callback function.- => Returns an
offmethod 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:thiscontext to use when calling the callback function.- => Returns an
offmethod to cancel the event subscription.
onDisconnected(callback, thisContext) => Function - shorthand for .on('disconnected', ...)
callback: Function: function to be called when websocket disconnected.thisContext: any:thiscontext to use when calling the callback function.- => Returns an
offmethod to cancel the event subscription.
onError(callback, thisContext) => Function - shorthand for .on('error', ...)
callback: Function: function to be called when an error occurs.thisContext: any:thiscontext to use when calling the callback function.- => Returns an
offmethod 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 request
middlewares: MiddlewareInterface[]- Array contains list of middlewares (implementedapplyMiddlewaremethod) implementation, theSubscriptionClientwill use the middlewares to modifyOperationOptionsfor every operation
status: number : returns the current socket's readyState
How it works?
- For GraphQL WebSocket protocol docs, click here
- This package also uses
AsyncIteratorinternally using iterall, for more information click here, or the proposal
The current version of this transport, also support a previous version of the protocol.
7 years ago