1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
---
layout: guide
doc_stub: false
search: true
section: GraphQL Pro - OperationStore
title: Getting Started
desc: Add GraphQL::Pro::OperationStore to your app
index: 1
pro: true
---
To use `GraphQL::Pro::OperationStore` with your app, follow these steps:
- [Check the dependencies](#dependencies) to make sure `OperationStore` is supported
- [Prepare the database](#prepare-the-database) for `OperationStore`'s data
- [Add `OperationStore`](#add-operationstore) to your GraphQL schema
- [Add routes](#add-routes) for the Dashboard and sync API
- [Update your controller](#update-the-controller) to support persisted queries
- {% internal_link "Add a client","/operation_store/client_workflow" %} to start syncing queries
## Dependencies
`OperationStore` requires two gems in your application environment:
- {% internal_link "ActiveRecord", "/operation_store/active_record_backend" %} or {% internal_link "Redis", "/operation_store/redis_backend" %} for persistence. (Using another ORM or backend? Please {% open_an_issue "Backend support request for OperationStore" %} to request support!)
- `Rack`: to serve the Dashboard and Sync API. (In Rails, this is provided by `config/routes.rb`.)
These are bundled with Rails by default.
## Prepare the Database
If you're going to store data with ActiveRecord, {% internal_link "migrate the database", "/operation_store/active_record_backend" %} to prepare tables for it.
## Add `OperationStore`
To hook up the storage to your schema, add the plugin:
```ruby
class MySchema < GraphQL::Schema
# Add it _after_ other tracing-related features, for example:
# use GraphQL::Tracing::DataDogTracing
# ...
use GraphQL::Pro::OperationStore
end
```
Make sure to add this feature _after_ other {% internal_link "Tracing", "/queries/tracing" %}-based features so that those other features will have access to the loaded query string. Otherwise, you may get `"No query string was present"` errors.
By default, it uses `ActiveRecord`. It also accepts:
- `redis:`, for using a {% internal_link "Redis backend", "/operation_store/redis_backend" %}; OR
- `backend_class:`, for implementing custom persistence.
Also, you can disable updates to "last used at" with `default_touch_last_used_at: false`. (This can also be configured per-query with `context[:operation_store_touch_last_used_at] = true|false`.)
## Add Routes
To use `OperationStore`, add two routes to your app:
```ruby
# config/routes.rb
# Include GraphQL::Pro's routing extensions:
using GraphQL::Pro::Routes
Rails.application.routes.draw do
# ...
# Add the Dashboard
# TODO: authorize, see the dashboard guide
mount MySchema.dashboard, at: "/graphql/dashboard"
# 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 {% internal_link "Client Workflow","/operation_store/client_workflow" %} for more info on how this endpoint is used.
`MySchema.dashboard` includes a web view to the `OperationStore`, visible at `/graphql/dashboard`. See the {% internal_link "Dashboard guide", "/pro/dashboard" %} for more details, including authorization.
{{ "/operation_store/graphql_ui.png" | link_to_img:"GraphQL Persisted Operations Dashboard" }}
`operation_store_sync` and `dashboard` are both Rack apps, so you can mount them in Rails, Sinatra, or any other Rack app.
__Alternatively__, you can configure the routes to load your schema lazily, during the first request:
```ruby
# Provide the fully-qualified class name of your schema:
lazy_routes = GraphQL::Pro::Routes::Lazy.new("MySchema")
mount lazy_routes.dashboard, at: "/graphql/dashboard"
mount lazy_routes.operation_store_sync, at: "/graphql/sync"
```
### With Visibility Profiles
You can apply a {% internal_link "visibility profile", "/authorization/visibility#visibility-profiles" %} to incoming operations by passing the profile name to `operation_store_sync`, for example:
```ruby
mount MySchema.operation_store_sync(visibility_profile: :public_api), at: "/graphql/sync"
# or:
mount lazy_routes.operation_store_sync(visibility_profile: :public_api), at: "/graphql/sync"
```
This will apply that profile to all newly-synced operations. (It doesn't affect operations that were already synced.)
## Update the Controller
Add `operation_id:` to your GraphQL context:
```ruby
# app/controllers/graphql_controller.rb
context = {
# Relay / Apollo 1.x:
operation_id: params[:operationId]
# Or, Apollo Link:
# operation_id: params[:extensions][:operationId]
}
MySchema.execute(
# ...
context: context,
)
```
`OperationStore` will use `operation_id` to fetch the operation from the database.
See {% internal_link "Server Management","/operation_store/server_management" %} for details about rejecting GraphQL from `params[:query]`.
## Next Steps
Sync your operations with the {% internal_link "Client Workflow","/operation_store/client_workflow" %}.
|