Docs
CreateRelayEnvironment

CreateRelayEnvironment

Batteries-included Relay Environment factory. Instead of manually writing the setup for Network, RecordSource, Store, fetch with retries, token refresh, redirect on expired session, and WebSocket for subscriptions, the consumer instantiates CreateRelayEnvironment with a few options and receives an Environment ready for use with react-relay.

Internally, this folder absorbs the infra modules that support the class: fetchQuery, fetchWithRetries, storage, subscriptionHandler, executeEnvironment, and the helpers file setupRelayEnvironment.helpers. These internals are not re-exported in the barrel — they are part of the implementation and can change without notice.

When to use

✅ Use when…🚫 Avoid when…
  • In any React application that uses Relay and needs JWT auth, automatic retries, or subscriptions.
  • When you want a single canonical point to configure the app's GraphQL backend, with sensible defaults.
  • If the app doesn't use Relay (use @apollo/client or another solution).
  • If you need fine-grained control over the Network (custom interceptors, multiple schemas, etc.) — in that case, prefer assembling the Environment by hand using relay-runtime directly.

Configuration

Only url is required. The most common options:

  • url — GraphQL HTTP endpoint.
  • authUrl — auth server endpoint (required with useAuthorization; and with authMode:'cookie', unless sessionCheckUrl:false).
  • socket — WebSocket endpoint (required with useSubscription).
  • authMode'bearer' (default) injects Authorization: Bearer; 'cookie' uses an httpOnly session (does not read a token or inject a header).
  • useAuthorization — in bearer mode, injects Authorization: Bearer <token> on each request.
  • credentialsRequestCredentials passed to the GraphQL/refresh fetches. Default 'include' in cookie mode; omitted in bearer.
  • sessionCheckUrl — overrides the session probe URL; false turns the probe off.
  • useRetries + retries — retry with backoff on 5xx/timeout errors.
  • useSubscription — enables GraphQL subscriptions via graphql-ws.
  • useCache + cacheTime + cacheSize — response caching via QueryResponseCache.
  • storageType'localStorage' (default) or 'cookie' (bearer mode only).
  • redirectOnError + loginRoute — redirects on detecting an expired session.
  • partnerX-Partner header for tenants/whitelabel.
  • usePersistedQueries + persistedOperationField — send only the build-time operation hash (server allowlist); see below.

The complete list (with defaults) is documented in the types in relayArgsInterface.

Auth: Bearer (default) vs. httpOnly cookie

  • authMode: 'bearer' — reads sessionToken from storage and injects Authorization: Bearer <token>; session probe at ${authUrl}user/me. Backwards compat: behavior of previous versions, unchanged.
  • authMode: 'cookie' — session via httpOnly + SameSite cookie (safe against XSS). Does not read a token or inject Authorization; credentials:'include' (default) makes the browser attach the cookie. The on-error refresh is a POST to authUrl with credentials:'include', with no probe to user/me.

Example

import { CreateRelayEnvironment } from '@apollion-dsi/relay/setupRelayEnvironment';
 
const { Environment, StorageHandler } = new CreateRelayEnvironment({
  url: 'https://api.example.com/graphql/',
  authUrl: 'https://api.example.com/auth/',
  socket: 'wss://api.example.com/graphql/',
  useAuthorization: true,
  useRetries: true,
  useSubscription: true,
  redirectOnError: true,
  loginRoute: '/login',
});
 
// Use with EnvironmentProvider — the single Relay provider, backing both
// useEnvironment() and every react-relay store hook. Don't also mount
// react-relay's RelayEnvironmentProvider yourself.
import { EnvironmentProvider } from '@apollion-dsi/relay';
 
function App() {
  return (
    <EnvironmentProvider environment={Environment}>
      <Routes />
    </EnvironmentProvider>
  );
}
 
// Manipulate tokens directly (e.g. after login) — bearer mode only.
StorageHandler.setTokens({ sessionToken: 'jwt...', refreshToken: 'r...' });

Example — httpOnly cookie session

const { Environment } = new CreateRelayEnvironment({
  url: 'https://api.example.com/graphql/',
  authUrl: 'https://api.example.com/auth/refresh/', // target of the on-401 refresh
  authMode: 'cookie',
  redirectOnError: true,
  loginRoute: '/login',
});
// No StorageHandler.setTokens — the httpOnly cookie is set by the
// server at login (Set-Cookie) and travels on its own via credentials:'include'.

Persisted queries (server-aligned hash allowlist)

With usePersistedQueries: true the client sends only the hash generated at build time by relay-compiler — the GraphQL text never leaves the build, so a query altered in the frontend is refused by the server, which also gains cache-by-hash. Requires persistConfig in the consumer's relay.config.json (the compiler writes the query map the server loads as its allowlist and stamps each artifact's id; without it, the first request throws a descriptive error).

const { Environment } = new CreateRelayEnvironment({
  url: 'https://api.example.com/graphql/',
  usePersistedQueries: true,
  // persistedOperationField: 'documentId', // if the server expects another field
});

Wire contract per transport:

  • Queries/mutations (HTTP): body { name, doc_id, variables } — no query key.
  • Uploads (multipart): the operations field carries { doc_id, variables, operationName }.
  • Subscriptions (graphql-ws): payload { operationName, query: '', variables, extensions: { doc_id } } — the server extracts the hash from payload.extensions.

The server must refuse raw text and unknown hashes replying 200 + { errors } (application/json) — a 4xx is swallowed by the client's retry layer instead of surfacing the GraphQL error.

Granular imports

// Granular — recommended when the consumer only needs the Environment.
import { CreateRelayEnvironment } from '@apollion-dsi/relay/setupRelayEnvironment';
 
// Via the root barrel — convenient.
import { CreateRelayEnvironment } from '@apollion-dsi/relay';

See also