Skip to Content
DocsSecurityPersisted OperationsGenerated Persisted Operations

Generate JSON files for Persisted Operations

You have several options for generating your Persisted Operations JSON files to upload to Stellate. These tools work for any type of OS and place the generated JSON file at the workspace-root where you run the command.

For your convenience, the following topics summarize how to use these tools to generate a JSON file. For details, we recommend that you read the source documentation in detail.

Using Relay

Relay is a convenient tool maintained by the Meta (formerly Facebook) product infrastructure engineering teams. To use it follow the Relay installation instructions.

Once Relay is installed, to start generating persisted-operations with the relay-compiler, do the following steps:

  1. Per the Relay instructions, edit the package.json file. Specify the persistConfig option in the Relay configuration section:

    "persistConfig": {
        "file": "./persisted_queries.json"
    }

    Read Local Persisted Queries in the Relay documentation for more details.

  2. Send the generated persisted_queries.json file to the Stellate server using the following CLI command:

  stellate persisted-operations push ./persisted_queries.json
 

When using the network layer fetch implementation to pass an ID parameter in the POST body (such as doc_id) instead of a query parameter, note the following:

⚠️

Stellate does not support body.doc_id, when sending persisted operations. You may have read instructions in the Relay Network Layer Changes to send body.doc_id. However, note that the spec to support this has no defined way for altering the base document body; it only supports query variables, extensions and operationName, where extensions are meant for these changes. In theory query is not allowed to be null but we implicitly agree to this contract in context of Persisted Operations.

Define the following, instead of using body.doc_id.

body: JSON.stringify({
  extensions: {
    persistedQuery: {
      version: 1,
      sha256Hash: operation.id
    }
  },
  variables,
}),

Using Apollo

You can use @apollo/persisted-query-lists package to generate your .json file for persisted queries. Read the Apollo documentation on Apollo Rover and Automatic persisted queries.

To use Rover, you need to follow the Apollo installation instructions. They are summarized as follows:

  1. Install @apollo/generate-persisted-query-manifest.
  2. Run npx generate-persisted-query-manifest to generate your persisted-operations file.
  3. Install A persisted queries the @apollo/persisted-query-lists package. This package contains helpers that work with the persisted queries link.
  4. Edit your Config file to send __typename

    You can use the following step if you intend to not send the hashes on to the origin server.

For Stellate and your GraphQL client (for example apollo-client) to understand the operations that are flowing through the CDN we need to have the __typename included in your documents. We can achieve this by adding that selection to every document through the configuration.

  1. Edit your apollo-persisted-query-lists configuration file. The file is called persisted-query-manifest.config.ts
  2. In the configuration file, include __typename for every selection

The following snippet illustrates the use of __typename in the configuration file.

persisted-query-manifest.config.ts
import { PersistedQueryManifestConfig, defaults } from "@apollo/generate-persisted-query-manifest";
import { SelectionNode, DefinitionNode, DocumentNode, Kind, parse, print } from 'graphql'
 
const formatNode = <
  T extends SelectionNode | DefinitionNode | DocumentNode,
>(
  node: T
) => {
  if ('definitions' in node) {
    const definitions: DefinitionNode[] = [];
    for (const definition of node.definitions) {
      const newDefinition = formatNode(definition);
      definitions.push(newDefinition);
    }
 
    return { ...node, definitions };
  }
 
  if ('selectionSet' in node) {
    const selections: SelectionNode[] = [];
    let hasTypename = node.kind === Kind.OPERATION_DEFINITION;
    if (node.selectionSet) {
      for (const selection of node.selectionSet.selections || []) {
        hasTypename =
          hasTypename ||
          (selection.kind === Kind.FIELD &&
            selection.name.value === '__typename' &&
            !selection.alias);
        const newSelection = formatNode(selection);
        selections.push(newSelection);
      }
 
      if (!hasTypename) {
        selections.push({
          kind: Kind.FIELD,
          name: {
            kind: Kind.NAME,
            value: '__typename',
          }
        };
      }
 
      return {
        ...node,
        selectionSet: { ...node.selectionSet, selections },
      };
    }
  }
 
  return node;
};
 
const config: PersistedQueryManifestConfig = {
  createOperationId(query) {
    const newNode = formatNode(parse(query));
    return defaults.createOperationId(print(newNode))
  }
};
 
export default config;

The prior code snippet is provided to supplement the Apollo documentation, as it currently does not address this topic in full.

Using GraphQL Code Generator

You can also use GraphQL Code Generator to generate your .json file for persisted queries.

Read the GraphQL Code Generator documentation for the details on using GraphQL Code Generator to create your .json file for persisted operations.

For information about using addTypenames for GraphQL Codegen, read the following topics:

Using URQL

URQL is a GraphQL client that can use one of the generated JSON files to send persisted-operations at runtime to Stellate and/or your origin server. Read the URQL documentation for more details about using this client.

Last updated on