Patching GraphQL Responses
Relevant source files
The following files were used as context for generating this wiki page:
Patching GraphQL Responses refers to the mechanism within @joindeed/prisma-auth that ensures returned data remains schema-compliant when authorization rules deny access to specific fields or types. Because Prisma models often have non-nullable constraints, the middleware must provide fallback values (such as empty strings or arrays) instead of returning null when a user lacks the required roles to view a resource.
Sources: src/patchResponse.ts:1-5, src/makeFieldConstraintMiddleware.ts:44-46
Architecture and Core Logic
The patching system operates within the GraphQL middleware layer. When a resolver executes, the authorization middlewares evaluate the @Auth annotations defined in the Prisma schema. If the granted check fails, the middleware replaces the actual result with a "safe" default value determined by the GraphQL return type.
Fallback Value Mapping
The system maps GraphQL return types to specific JavaScript/TypeScript primitives to maintain type integrity.
| GraphQL Type Pattern | Patch Result | Description |
|---|---|---|
String! | '' (Empty String) | Prevents null errors for non-nullable strings. |
[...]! (List) | [] (Empty Array) | Ensures non-nullable lists return an empty set. |
| Other Types | null | Default behavior for nullable fields. |
Sources: src/patchResponse.ts:7-17, src/patchResponse.test.ts:4-9
Integration in Middleware Flow
The response patching logic is triggered at two primary levels:
- Field Level: Triggered when a specific field on a model has restricted access.
- Type Level: Triggered when a 1-to-1 relation or a specific return type is restricted.
Component Implementation
patchResponse Function
The patchResponse function is a utility that inspects the returnType provided by the GraphQL info object. It uses regular expressions to identify non-nullable lists and specific string types.
export const patchResponse = (returnType: unknown): null | [] | '' => {
const returnTypeString = String(returnType)
if (returnTypeString === 'String!') {
return ''
}
if (/^\[.+\]!$/.test(returnTypeString)) {
return []
}
return null
}
Sources: src/patchResponse.ts:7-17
Middleware Execution Sequence
Response patching occurs at the end of the middleware execution if authorization fails. The following sequence diagram illustrates how makeTypeConstraintMiddleware uses patching:
Usage Contexts
The authorization system employs patching in different scenarios to ensure the GraphQL client receives a valid response even when data is hidden:
- Field Constraints: In
makeFieldConstraintMiddleware.ts, if thereadRolescheck returnsfalse, the middleware returns the result ofpatchResponse(info.returnType). - Type Constraints: In
makeTypeConstraintMiddleware.ts, the middleware extracts the type name and checks roles. If the user is not granted access, it patches the response. This is particularly relevant for 1-to-1 relations likePurchase.User.
Sources: src/makeFieldConstraintMiddleware.ts:44-46, src/makeTypeConstraintMiddleware.ts:60-62
Summary
Patching GraphQL Responses provides a safety net for the declarative authorization layer. By converting denied access into schema-compliant fallback values, it prevents runtime GraphQL errors caused by null values in non-nullable fields. This mechanism allows the project to enforce strict security policies at the Prisma model level while maintaining a stable API for the consumer.
Sources: README.md:1-10, src/patchResponse.ts:1-5