Goal: perform a basic query of our database through an autogenerated GraphQL backend.

For this task we use Postgraphile, a tool modelled on Postgrest that generates an API server based on introspecting the database schema.

We will also use the Apollo GraphQL client and the vue-apollo integration.
These seem to be the most widely used libraries.

Connecting to GraphQL

In your main entry point, you can use this setup code:

import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import VueApollo from 'vue-apollo';

const localApi = "/api";

const client = new ApolloClient({
    link: new HttpLink({ uri: localApi }),
    cache: new InMemoryCache()
});

const apolloProvider = new VueApollo({
    defaultClient: client
});

Vue.use(VueApollo);

document.addEventListener("DOMContentLoaded", e => {
    const vueInstance = new Vue({
        render: h => h(ApplicationRoot),
        provide: apolloProvider.provide()
    });
    vueInstance.$mount('#vue-outlet');
});

Your API will be available under the "/api" prefix to avoid CORS issues. You configure this in webpack with the following stanza:

devServer: {
    port: 57242,
    proxy: {
        "/api": {
            target: "http://localhost:5000/graphql",
            pathRewrite: {"^/api": ""}
        }
    }
}

The Postgraphile server will appear on port 5000 by default.

Starting the server

This is extremely simple.

amoe@klauwier $ sudo yarn global add postgraphile
amoe@klauwier $ postgraphile -c postgres://localhost/mol_viewer

PostGraphile server listening on port 5000 🚀

  ‣ Connected to Postgres instance postgres://localhost:5432/mol_viewer
  ‣ Introspected Postgres schema(s) public
  ‣ GraphQL endpoint served at http://localhost:5000/graphql
  ‣ GraphiQL endpoint served at http://localhost:5000/graphiql

* * *

Your database here is mol_viewer. A service should start on port 5000.

Writing a sample query

Using the module graphql-tag, you can define your queries using template literals. This will syntax-check your queries at compile time.

const demoQuery = gql`
{
  allParticipants {
    nodes {
     reference
    }
  }
}`

This looks slightly weird, but the important thing to know here is that I have a table already in my database schema called participant. Postgraphile has inferred a collection of objects, therefore, called allParticipants. My table has a field called reference (which can be of any type). nodes is (I believe) a Postgraphile-specific property of the list allParticipants. That is to say, the text nodes above has nothing to do with the database schema of mol_viewer, rather it's an artifact of using Postgraphile.

Link the query to your page

When you have set up vue-apollo, you have access to a apollo property on your Vue instance. In this case it looks as such.

apollo: {
    allParticipants: demoQuery
}

Here, allParticipants is a name which must be the same as the top-level result of the query. It's not just an arbitrary identifier.

Now, allParticipants field exists in your component's data object. The query is automatically made when you load your page, and allParticipants will be populated. You can demonstrate this through the simple addition of {{allParticipants}} to your template.

To iterate through the query results, you have to consider that the results of the query are always shaped like the query itself. So your basic list of the results will look as follows.

<ol>
  <li v-for="node in allParticipants.nodes">
    {{node.reference}}
  </li>
</ol>

Filtering

Postgraphile supports filtering using the simple condition on the auto-generated allParticipants field. For instance, imagine filtering by a given reference. You'd do allParticipants(condition: {reference: "A14"}). Only simple equality is supported out of the box (!). Plugins are available.