GraphQL
The GraphQL transport provides a browser-only execution layer for GraphQL queries and mutations in ONECMS.
It is intentionally strict and minimal. Its purpose is to execute predefined GraphQL operations against the backend while enforcing architectural boundaries and misuse guards.
Scope and Responsibility
The GraphQL transport is responsible for:
- Executing GraphQL queries and mutations in the browser
- Enforcing execution invariants (environment, structure, access patterns)
- Providing a stable, framework-agnostic execution layer
The GraphQL transport is not responsible for:
- Defining GraphQL operations
- Managing application state
- Handling UI lifecycle or routing
- Performing business logic or orchestration
- Inferring authentication implicitly
Execution Environment
- GraphQL execution is browser-only
- Any attempt to initialize the GraphQL client or execute an operation in a server or RSC environment must:
- throw immediately
- fail loudly
This transport must not depend on:
- Next.js request context
- Server headers or cookies
- RSC or Server Actions
- Framework-specific lifecycle hooks
Browser-only does not mean framework-coupled.
Single Source of Truth for Operations
All GraphQL operations must be defined exclusively under the graphql/ directory.
Rules:
- No inline GraphQL strings outside this folder
- One operation per file
- File name must match the exported operation name
- Operation names must be unique and stable
This guarantees:
- discoverability
- consistency
- safe refactoring
- predictable ownership
Strict Read / Write Separation
GraphQL operations are separated by intent:
queries/
- read-only
- must not cause side effects
mutations/
- write-only
- must not be used for data-fetching-only flows
Mixing read and write concerns is forbidden.
Service-Centric Access
GraphQL operations must be consumed only via services.
The following layers must never import directly from graphql/:
- components
- modules
- hooks
- app routes
Services act as the boundary that:
- binds GraphQL operations to domain intent
- handles orchestration
- translates errors where needed
Auth Handling
Authentication is operation-scoped, not client-scoped.
- GraphQL client initialization must not depend on auth
- Individual operations may:
- explicitly require authentication
- throw
auth.unauthenticatedif required and missing
- Public operations must remain callable pre-auth
This prevents implicit coupling between transport initialization and auth state.
Error Handling
- GraphQL errors are surfaced explicitly
- No silent failures
- No implicit retries
- No UI-specific error shaping
Error translation (if any) belongs in services, not the transport.
Misuse Guards
The transport must explicitly guard against:
- server-side execution
- RSC invocation
- framework-coupled imports
- implicit auth assumptions
Any violation should fail fast and loudly.