Skip to main content

Context

Context is a simple object that represents, well, the context of what's happening.

export interface Context<TViewer extends Viewer = Viewer> {
getViewer(): TViewer;
cache?: cache;
}

There's the simple Context interface shown above which has a getViewer method which returns the Viewer and a cache property which is used for context-caching.

RequestContext

There's also the RequestContext interface which is used during the request-path e.g. in GraphQL queries and mutations:

export interface RequestContext extends Context {
authViewer(viewer: Viewer): Promise<void>;
logout(): Promise<void>;
request: IncomingMessage;
response: ServerResponse;
}

authViewer

authViewer is used to change who the currently logged in Viewer is. It's called by the built-in auth to change the viewer from the previous one - often the LoggedOutViewer - to the newly logged in Viewer.

logout

Changes the viewer to the LoggedOutViewer.

request

Instance of HTTP Request object.

response

Instance of HTTP Response object.

New Request

It's highly recommended that a new Context is created for each new request. The framework comes with a helper method buildContext which helps with this. It takes the request and response above and returns a new RequestContext. It calls into the auth system to ensure the right Viewer is returned.

Since we implement context-caching, we want to make sure that any data cached in one request is not inadvertently served incorrectly in a different request.

The default generated GraphQL handler helps with that:

src/graphql/index.ts
//...
app.use(
"/graphql",
async (req, res) => {
if (shouldRenderGraphiQL(req)) {
res.send(renderGraphiQL());
} else {
const { operationName, query, variables } = getGraphQLParameters(req);
const result = await processRequest({
operationName,
query,
variables,
request: req,
schema,
contextFactory: async (executionContext: ExecutionContext) => {
return buildContext(req, res);
},
});
await sendResult(result, res);
}
},
);

This is an express handler which uses a few methods from graphql-helix, builds the context via buildContext and that context is passed all the way down to each GraphQL resolver.

All of the above can be overriden or changed as needed if your needs are more complicated. The src/graphql/index.ts file is generated only once.