Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 69 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
# Apollo Phoenix Websocket
# APW - Apollo Phoenix Websocket

<a href="https://travis-ci.org/vic/apollo-phoenix-websocket"><img src="https://travis-ci.org/vic/apollo-phoenix-websocket.svg"></a>
[![help maintain this lib](https://img.shields.io/badge/looking%20for%20maintainer-DM%20%40vborja-663399.svg)](https://twitter.com/vborja)


This node module implements an [Apollo GraphQL Network Layer] using [Phoenix Channels]

Since version `0.6.0`, all Apollo operations are supported: queries, mutations, watchQueries (pooling) and
subscriptions.

Using the [Apollo Client], queries and mutations resolve to promises, and watchQueries and
subscriptions resolve to observables.

See the Apollo client [documentation][Apollo Client] for more info on how to invoke your gql backend.

For those wondering why to use Apollo instead of directly executing your GQL queries via a simple
websocket, Apollo has an internal store that let's you optimize the queries and only ask for what it
needs, much like Facebook's Relay does.


## Installation

```shell
Expand All @@ -14,44 +27,63 @@ npm install --save apollo-phoenix-websocket

## Usage

Just import the `createNetworkInterface` from APW and use it to create an ApolloClient.

The `networkInterface` function takes an options object, the only required
property is `uri` which specifies your endpoint websocket address.

```javascript
import ApolloClient from 'apollo-client'
import {createNetworkInterface} from 'apollo-phoenix-websocket'

// See the Options section
const networkInterface = createNetworkInterface({
uri: 'ws://localhost:4000/socket',
channel: {
topic: 'gql:query'
}
})
// Nothing to configure if you are using an Absinthe backend
// Otherwise take a look at the Options section.
const networkInterface = createNetworkInterface({uri: 'ws://localhost:4000/socket'})

const apollo = new ApolloClient({networkInterface})
```

## Options

The `networkInterface` expects an object with at least the following
properties:
Most likely, (as you are looking for a phoenix-websocket transport) you might be using
the [Absinthe] library to implement your Elixir GQL server. APW is configured by default
to work out of the box with an [Absinthe backend].

But if need araises, you can supply some advanced options to customize how it works.
Here's is a commented example of the options that you can set for APW:


```javascript
createNetworkInterface({

- `uri`: The Phoenix websocket uri to connect into
- `channel.topic`: A topic name where graphql queries will be sent
// The websockets endpoint to connect to, like wss://example.com:4000/socket
uri: WS_URI,

These other have default values:
// how to send queries and mutations
channel: {
topic: '__absinthe__:control',
event: 'doc',
},

- `params`: The params sent to Phoenix when connecting to the socket
- `channel.params`: The params sent to Phoenix when joining the channel
- `channel.in_msg`: Name of the `handle_in` message on the channel, defaults to 'gql'
// for using websocket subscriptions
subscription: (subscriptionResponse) => ({
topic: subscriptionResponse.subscriptionId,
event: 'subscription:data',

- `Socket`: A function taking `(url, options)` that returns a Phoenix Socket implementation.
Defaults to:
`(url, options) => new PhoenixSocket(url, options)`
// extract the data from the event payload
map: payload => payload.result.data,

Where `PhoenixSocket` is the
reference implementation from the [Phoenix Framework](https://github.com/phoenixframework/phoenix).
This option lets you use an already existing socket or customize how it gets created.

- `logger`: A function or `true` used for debugging.
// what to do when unsubscribing
off: controlChannel => {
controlChannel.push('unsubscribe', subscriptionResponse.subscriptionId)
}
}),

// If you want to reuse an existing Phoenix Socket, just provide a function
// for APW to get it. By default, it will use the Phoenix Socket module.
Socket: options => new Socket(options),
})
```

## Middlewares

Expand Down Expand Up @@ -92,46 +124,30 @@ networkInterface.useAfter([{
}])
```

## Phoenix Channel
## Absinthe backend

This example shows how you could use [Absinthe] to run incomming queries
[Absinthe] is an amazing project (kudos to @benwilson512 et al.). It's actually very
simple to create a GQL backend with it.

Take a look at the following places for more information:

- The [Absinthe guide][Absinthe] itself for getting started.
- [Absinthe Phoenix] for implementing websocket subscriptions on your endpoint.
- [Absinthe.Schema#subscription/2][Absinthe Subscription] docs for how to setup your schema

```javascript
const options = {
uri: 'ws://localhost:4000/socket',
channel: {
topic: 'gql:query',
params: {foo: true},
in_msg: 'run'
}
}
```

```elixir
defmodule MyApp.GQL.Channel do
use Phoenix.Channel

def join("gql:query", _params = %{"foo" => true}, socket) do
{:ok, socket}
end

def handle_in("run", params = %{"query" => query}, socket) do
variables = Map.get(params, "variables", %{})
options = [variables: variables]
{:ok, result} = Absinthe.run(query, MyApp.GQL.Schema, options)
{:reply, {:ok, result}, socket}
end
end
```

# Made with love <3

If you want to provide feedback or even better if you want to contribute some code feel free to open a [new issue].
If you want to provide feedback or even better if you want to contribute some code feel free to open a [new issue].
Possible thanks to the awesome work of [our contributors].


[Apollo Client]: http://dev.apollodata.com/core/apollo-client-api.html
[Apollo GraphQL Network Layer]: http://dev.apollodata.com/core/network.html
[Phoenix Channels]: http://www.phoenixframework.org/docs/channels
[Absinthe]: http://absinthe-graphql.org/
[new issue]: https://github.com/vic/apollo-phoenix-websocket/issues
[our contributors]: https://github.com/vic/apollo-phoenix-websocket/graphs/contributors
[Absinthe Phoenix]: https://github.com/absinthe-graphql/absinthe_phoenix
[Absinthe Subscription]: https://hexdocs.pm/absinthe/1.4.0-beta.1/Absinthe.Schema.html#subscription/2
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apollo-phoenix-websocket",
"version": "0.5.1",
"version": "0.6.0",
"description": "Apollo networkInterface using Phoenix websockets",
"main": "lib/index.js",
"files": [
Expand Down Expand Up @@ -43,6 +43,6 @@
"dependencies": {
"apollo-client": "^0.6.0",
"phoenix": "^1.2.1",
"ramda": "^0.23.0"
"ramda": "^0.24.1"
}
}
Loading