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… |
|---|---|
|
|
Configuration
Only url is required. The most common options:
url— GraphQL HTTP endpoint.authUrl— auth server endpoint (required withuseAuthorization; and withauthMode:'cookie', unlesssessionCheckUrl:false).socket— WebSocket endpoint (required withuseSubscription).authMode—'bearer'(default) injectsAuthorization: Bearer;'cookie'uses an httpOnly session (does not read a token or inject a header).useAuthorization— inbearermode, injectsAuthorization: Bearer <token>on each request.credentials—RequestCredentialspassed to the GraphQL/refresh fetches. Default'include'in cookie mode; omitted in bearer.sessionCheckUrl— overrides the session probe URL;falseturns the probe off.useRetries+retries— retry with backoff on 5xx/timeout errors.useSubscription— enables GraphQL subscriptions viagraphql-ws.useCache+cacheTime+cacheSize— response caching viaQueryResponseCache.storageType—'localStorage'(default) or'cookie'(bearermode only).redirectOnError+loginRoute— redirects on detecting an expired session.partner—X-Partnerheader 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'— readssessionTokenfrom storage and injectsAuthorization: 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 injectAuthorization;credentials:'include'(default) makes the browser attach the cookie. The on-error refresh is aPOSTtoauthUrlwithcredentials:'include', with no probe touser/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 }— noquerykey. - Uploads (multipart): the
operationsfield carries{ doc_id, variables, operationName }. - Subscriptions (
graphql-ws): payload{ operationName, query: '', variables, extensions: { doc_id } }— the server extracts the hash frompayload.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
- Full API:
setupRelayEnvironment.ts. - Configuration types:
relayArgsInterface. - Environment provider/hook:
useEnvironment. - Official documentation: Relay Environment (opens in a new tab).