Vulcan in a Nutshell

The best way to understand how Vulcan works is to consider its three main aspects: the role of the schema, how Vulcan reads data, and how Vulcan writes data.

Overview

/images/how-vulcan-works.svg

The Schema

At its core, a Vulcan schema is just a JavaScript object containing a list of fields such as name, _id, createdAt, description, etc. describing a type of document (a movie, a post, a photo, a review, and so on).

The schema is what defines how a Collection (you might also be more familiar with the equivalent term “model”) behaves, and it fulfills many important functions:

  1. It’s used to generate your GraphQL schema, which in turn controls your app’s GraphQL API.
  2. It’s used to control permissions.
  3. It’s used to generate forms.

Reading Data (Queries)

Reading data basically means getting data from your database all the way to the user’s browser.

Let’s assume we want to take a list of movies currently stored in our database and display it inside a Movies.jsx component. Here’s a quick overview of the entire data lifecycle:

Component

The Movies.jsx component expects a results prop. But how will it receive it?

Hook/Higher-Order Component

In order to receive that prop, the component will need to be wrapped with the withMulti higher-order component. You just need to specify the appropriate Collection, and optionally also specify a fragment to define which document fields to load.

Alternatively, you can do the same thing through the useMulti hook.

GraphQL Query

The withMulti HoC (or useMulti hook) will trigger an Apollo query to the app’s GraphQL endpoint using the movies query resolver.

This is the same kind of query you would write manually in any regular GraphQL app, but in this case the query is auto-generated by the HoC or hook.

Resolver

The query triggers a resolver function. The job of that function is to take the query arguments and output the corresponding data in return, after making sure the current user is authorized to access said data.

Connector

Finally, the resolver queries the database to retrieve the data. This is done through a connector, a function that translates a generic find request into instructions specific to the current database.

Writing Data (Mutations)

Now let’s consider the opposite operation: writing data, such as editing a movie’s description using a form.

Component

First, you should know that the movie update form component can be automatically generated from your schema, meaning you don’t actually need to code it or worry about hooking it up to your GraphQL API.

Hook/Higher-Order Component

That form is wrapped with the withUpdate HoC.

GraphQL Query

The HoC in turn will call the updateMovie mutation on the server (which again can be automatically generated from default mutations).

Resolver

On the server, the update resolver takes in the mutation’s arguments (an object indicating which document to update, as well as the payload containing the actual changes) and after some permission checks to make sure the current user is authorized to perform the mutation passes them on to the mutator.

Mutator

updateMovie will then call a boilerplate mutator which will perform validation based on your schema, and finally call the database connector.

Connector

The database connector then modifies the document inside your database.

Edit on GitHub