Getting Started

To use GraphQL::Pro::OperationStore with your app, follow these steps:

Dependencies

OperationStore requires two gems in your application environment:

These are bundled with Rails by default.

Prepare the Database

GraphQL::Pro::OperationStore requires some database tables. You can add these with a migration:

$ rails generate migration SetupOperationStore

Then open the migration file and add:

# ...
# implement the change method with:
def change
  create_table :graphql_clients do |t|
    t.column :name, :string, null: false
    t.column :secret, :string, null: false
    t.timestamps
  end
  add_index :graphql_clients, :name, unique: true
  add_index :graphql_clients, :secret, unique: true

  create_table :graphql_client_operations do |t|
    t.references :graphql_client, null: false
    t.references :graphql_operation, null: false
    t.column :alias, :string, null: false
    t.timestamps
  end
  add_index :graphql_client_operations, [:graphql_client_id, :alias], unique: true, name: "graphql_client_operations_pairs"

  create_table :graphql_operations do |t|
    t.column :digest, :string, null: false
    t.column :body, :text, null: false
    t.column :name, :string, null: false
    t.timestamps
  end
  add_index :graphql_operations, :digest, unique: true

  create_table :graphql_index_entries do |t|
    t.column :name, :string, null: false
  end
  add_index :graphql_index_entries, :name, unique: true

  create_table :graphql_index_references do |t|
    t.references :graphql_index_entry, null: false
    t.references :graphql_operation, null: false
  end
  add_index :graphql_index_references, [:graphql_index_entry_id, :graphql_operation_id], unique: true, name: "graphql_index_reference_pairs"
end

Add OperationStore

To hook up the storage to your schema, add the plugin:

MySchema = GraphQL::Schema.define do
  # ...
  use GraphQL::Pro::OperationStore
end

Add Routes

To use OperationStore, add two routes to your app:

# config/routes.rb

# Include GraphQL::Pro's routing extensions:
using GraphQL::Pro::Routes

Rails.application.routes.draw do
  # ...
  # Add the UI
  # TODO: authorize, see below
  mount MySchema.ui, at: "/graphql/ui"
  # Add the Sync API (authorization built-in)
  mount MySchema.operation_store_sync, at: "/graphql/sync"
end

MySchema.operation_store_sync receives pushes from clients. See Client Workflow for more info on how this endpoint is used.

MySchema.ui is a web view to the OperationStore, visible at /graphql/ui:

GraphQL UI

The are both Rack apps, so you can mount them in Sinatra or any other Rack app.

Authorizing the UI

You should only allow admin users to see /graphql/ui because it allows viewers to delete stored operations.

Use Rails routing constraints to restrict acccess to authorized users, for example:

# Check the secure session for a staff flag:
STAFF_ONLY = ->(request) { request.session["staff"] == true }
# Only serve the GraphQL UI to staff users:
constraints(STAFF_ONLY) do
  mount MySchema.ui, at: "/graphql/ui"
end

Update the Controller

Add operation_id: to your GraphQL context:

# app/controllers/graphql_controller.rb
context = {
  # ...
  operation_id: params[:operationId]
}

MySchema.execute(
  # ...
  context: context,
)

OperationStore will use stored_operation to fetch the operation from the database.

See Server Management for details about rejecting GraphQL from params[:query].

Next Steps

Sync your operations with the Client Workflow .