VOOZH about

URL: https://deepwiki.com/mathsgod/light/3.3-graphql-integration

⇱ GraphQL Integration | mathsgod/light | DeepWiki


Loading...
Last indexed: 31 January 2026 (cf9511)
Menu

GraphQL Integration

Purpose and Scope

This page documents how the Light\App class integrates with the GraphQLite-based GraphQL subsystem. It covers the initialization and configuration of the GraphQL server, schema factory setup, type mapper registration, authentication/authorization service binding, and the automatic permission discovery system that scans PHP attributes.

For information about the broader GraphQL API layer including controllers and type definitions, see GraphQL API. For details on schema generation mechanics, see Schema Generation and Type System. For RBAC-specific integration, see RBAC Integration.


GraphQL Server Initialization

The Light\App constructor initializes the GraphQL server through the Light\GraphQL\Server class, which wraps the TheCodingMachine GraphQLite library. This initialization occurs after the dependency injection container is set up but before RBAC and filesystem configuration.


Diagram: GraphQL Server Initialization Sequence

The initialization process configures caching behavior based on the application mode. In production mode (mode=prod), schema caching has no expiration (defaultLifetime=0), while in development mode it expires after 15 seconds to allow rapid iteration.

Sources: src/App.php104-127


Schema Factory Configuration

The SchemaFactory is the core component responsible for generating the GraphQL schema from PHP classes. The App class configures it with namespace scanning and custom type mappers.

Namespace Registration


Diagram: Namespace Scanning Configuration

The factory scans the Light\ namespace for GraphQL types, queries, and mutations. The addNamespace("Light") call instructs GraphQLite to examine all classes in this namespace for GraphQL annotations like #[Type], #[Query], #[Mutation], and #[Field].

Configuration MethodPurposeLocation
addNamespace()Registers namespaces to scan for GraphQL classessrc/App.php125
addTypeMapperFactory()Registers custom type conversion logicsrc/App.php126
setAuthenticationService()Binds authentication contextsrc/App.php529
setAuthorizationService()Binds authorization checkssrc/App.php530

Sources: src/App.php121-130

Type Mapper Factory

The custom Light\Db\GraphQLite\Mappers\TypeMapperFactory is registered to handle conversion between database types and GraphQL types. This enables automatic mapping of Light\Db\Query results to GraphQL lists and proper handling of database model objects as GraphQL types.


Diagram: Type Mapper Conversion Flow

Sources: src/App.php126


Authentication and Authorization Service Binding

The GraphQL schema factory requires authentication and authorization services to enforce security annotations. These services are injected during request processing rather than at initialization time, allowing per-request user context.

Service Injection Sequence


Diagram: Authentication Service Injection During Request Processing

The Auth\Service class implements both the authentication and authorization interfaces required by GraphQLite. When a resolver method is annotated with #[Logged] or #[Right("permission")], the factory uses these services to:

  1. Authentication (#[Logged]): Verify that a valid JWT token exists and load the corresponding User object
  2. Authorization (#[Right("permission")]): Check if the authenticated user has the specified permission via the RBAC system

Sources: src/App.php526-535

Dependency Injection Integration

The SchemaFactory is configured with the application's dependency injection container, enabling automatic injection of services into GraphQL resolvers via the #[Autowire] annotation:


Diagram: Dependency Injection in GraphQL Resolvers

Sources: src/App.php68-147


Permission Discovery System

The Light\App class implements an automatic permission discovery system that scans PHP attributes across the codebase to build a comprehensive list of all permissions used in the system. This enables dynamic permission management without hardcoding permission lists.

Discovery Process

The getPermissions() method scans multiple locations for the #[Right("permission")] attribute:


Diagram: Permission Discovery Algorithm

Implementation Details

Discovery SourceScanning MethodExample Permissions
Core Controllersglob(__DIR__ . "/Controller/*.php")user.list, user.create, user.update
Core Modelsglob(__DIR__ . "/Model/*.php")Model-specific permissions
Core Typesglob(__DIR__ . "/Type/*.php")Type field permissions
Database Classesglob(__DIR__ . "/Database/*.php")Database operation permissions
External ControllersComposerFinder::inNamespace("Controller")Custom controller permissions
External ModelsComposerFinder::inNamespace("Model")Custom model permissions
MenusgetMenusPermission($this->menus)fs, config, etc.
RBAC System$this->rbac->getPermissions()Role-based permissions

The discovery process uses PHP's Reflection API to examine methods and extract #[Right] attribute arguments:


Permission Filtering Rules:

  1. Permissions starting with # are filtered out (these are internal role markers like #administrators)
  2. Duplicate permissions are removed via array_unique()
  3. The final list is sorted alphabetically

Sources: src/App.php392-472

Usage in Authorization

The discovered permissions are used by:

  • Admin UI: Populate permission selection dropdowns for role configuration
  • RBAC System: Validate that assigned permissions exist in the codebase
  • Documentation: Generate permission reference documentation
  • Type\App: Exposed via getPermissions() GraphQL field for frontend consumption

Sources: src/Type/App.php190-193


Query Execution Pipeline

The execute() method handles the actual GraphQL query execution. It processes the request body, creates the schema, and executes the query with proper context.


Diagram: GraphQL Query Execution Flow

Key Execution Steps

StepComponentResponsibility
1. Upload ProcessingUploadMiddlewareConvert multipart/form-data uploads to PSR-7 UploadedFile objects
2. Body Parsingexecute()Extract query and variables from request body
3. Schema CreationSchemaFactoryGenerate/retrieve cached GraphQL schema
4. Context CreationContextCreate execution context (auth already in factory)
5. Query ExecutionGraphQL::executeQuery()Parse, validate, and execute the query
6. Error HandlingApp::handle()Include debug info in dev mode, hide in production
7. Response FormattingJsonResponseReturn JSON with UTF-8 encoding

Sources: src/App.php154-170 src/App.php567-579

Schema Caching Strategy

The schema creation is cached to avoid re-parsing PHP classes on every request:

  • Development Mode: Cache expires after 15 seconds, allowing quick iteration
  • Production Mode: Cache never expires, maximizing performance

The cache key includes the namespace and type mapper configuration, ensuring schema regeneration when configuration changes.

Sources: src/App.php104-119


GraphQL Type Registration

The main entry point for GraphQL queries is the Light\Type\App class, which is automatically discovered by the schema factory due to its #[Type] attribute. This class exposes numerous fields that serve as the root of the GraphQL query tree.

Root Query Fields


Diagram: Root Query Fields Exposed by Light\Type\App

Field Annotation Examples

The fields in Light\Type\App demonstrate various GraphQL features:

Annotation PatternExample FieldPurpose
#[Field] onlygetVersion()Simple scalar field, no security
#[Field] #[Logged]getMenus()Requires authentication
#[Field] #[Right("perm")]listUser()Requires specific permission
#[Field(outputType: "mixed")]getCustomFieldSchema()Returns untyped JSON
#[Autowire] App $appMultipleInjects Light\App instance
#[InjectUser] User $usergetMenus()Injects authenticated user

Sources: src/Type/App.php28-541


Integration with Request Handler

The App class implements both MiddlewareInterface and RequestHandlerInterface, allowing it to participate in the request processing pipeline as both middleware and final handler.


Diagram: Request Handler Integration

The middleware stage (process()) is responsible for:

  1. Handling OPTIONS requests for CORS
  2. Parsing JSON request bodies
  3. Processing multipart file uploads
  4. Creating per-request Auth\Service instance
  5. Binding authentication/authorization services to the schema factory
  6. Injecting request-specific objects into the DI container

The handler stage (handle()) is responsible for:

  1. Executing the GraphQL query via execute()
  2. Formatting the response with appropriate debug information
  3. Returning a PSR-7 JSON response

Sources: src/App.php38 src/App.php500-537 src/App.php154-170


Summary

The GraphQL integration in Light\App provides a comprehensive configuration layer that:

  • Initializes the GraphQLite server with environment-appropriate caching
  • Configures the schema factory with namespace scanning and type mappers
  • Binds authentication and authorization services for security enforcement
  • Discovers permissions automatically from PHP attributes across the codebase
  • Executes queries with proper context, error handling, and response formatting
  • Integrates with the PSR-15 middleware pipeline for request processing

This architecture enables declarative GraphQL API development where developers add #[Field], #[Logged], and #[Right] attributes to methods, and the system automatically generates the schema, enforces security, and exposes the functionality to clients.

Sources: src/App.php59-147 src/App.php154-170 src/App.php392-472 src/App.php500-537 src/App.php567-579 src/Type/App.php28-541