diff --git a/.ai/AGENTS.md b/.ai/AGENTS.md index 6c6d82d71b..596f0e557d 100644 --- a/.ai/AGENTS.md +++ b/.ai/AGENTS.md @@ -45,7 +45,8 @@ docker compose exec php vendor/bin/phpunit tests/Unit/Path/To/TestFile.php ### Directive System -Directives are the core extension mechanism. Located in `src/Schema/Directives/`. +Directives are the core extension mechanism. +Located in `src/Schema/Directives/`. - `BaseDirective` - Abstract base class for all directives, provides common utilities - Directive interfaces in `src/Support/Contracts/` define capabilities: @@ -124,6 +125,8 @@ $user = User::create([ - Never use `final` in `src/`, always in `tests/` - Full namespace in PHPDoc (`@var \Full\Namespace\Class`), imports in code - Code elements with `@api` have stability guarantees between major versions +- Use [Semantic Line Breaks](https://sembr.org) for prose in markdown and multiline comments +- Default to one sentence per line and avoid comma/clause-only line breaks ## Pull Requests diff --git a/CHANGELOG.md b/CHANGELOG.md index c52349b7a0..43ecd7683f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). +This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). You can find and compare releases at the [GitHub release page](https://github.com/nuwave/lighthouse/releases). @@ -1466,8 +1466,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added -- Add `Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective` interface to allow - overwriting the default query complexity calculation https://github.com/nuwave/lighthouse/pull/1947 +- Add `Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective` interface to allow overwriting the default query complexity calculation https://github.com/nuwave/lighthouse/pull/1947 - Allow omitting `name` in `@scope` by defaulting to the argument name https://github.com/nuwave/lighthouse/pull/1957 ### Changed @@ -1493,8 +1492,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added -- Add `--federation` option to `lighthouse:print-schema` command to print the schema - with federation directives and without federation spec additions, like `_service.sdl` https://github.com/nuwave/lighthouse/pull/1932 +- Add `--federation` option to `lighthouse:print-schema` command to print the schema with federation directives and without federation spec additions, like `_service.sdl` https://github.com/nuwave/lighthouse/pull/1932 ## v5.22.5 @@ -1938,18 +1936,13 @@ You can find and compare releases at the [GitHub release page](https://github.co - `Nuwave\Lighthouse\Exceptions\ValidationException` no longer extends `Illuminate\Validation\ValidationException` https://github.com/nuwave/lighthouse/pull/1185 - Move validation related classes into namespace `Nuwave\Lighthouse\Validation` https://github.com/nuwave/lighthouse/pull/1185 - Run `ArgDirectives` in distinct phases: Sanitize, Validate, Transform https://github.com/nuwave/lighthouse/pull/1185 -- The directive interfaces `ArgBuilderDirective`, `ArgTransformerDirective` and `ArgDirectiveForArray` - extend `Directive` instead of `ArgDirective` https://github.com/nuwave/lighthouse/pull/1185 -- Change the autogeneration of the `OrderByClause` input for `@orderBy`, the - argument `field` is now always called `column` https://github.com/nuwave/lighthouse/pull/1337 +- The directive interfaces `ArgBuilderDirective`, `ArgTransformerDirective` and `ArgDirectiveForArray` extend `Directive` instead of `ArgDirective` https://github.com/nuwave/lighthouse/pull/1185 +- Change the autogeneration of the `OrderByClause` input for `@orderBy`, the argument `field` is now always called `column` https://github.com/nuwave/lighthouse/pull/1337 - Names for autogenerated types are now prepended with the name of the fields parent type - This affects `@orderBy`, `@whereConditions` and `@whereHasConditions` https://github.com/nuwave/lighthouse/pull/1337 -- `__invoke` is now the only supported method name for convention based - field resolver classes https://github.com/nuwave/lighthouse/pull/1422 -- Change `Nuwave\Lighthouse\Support\Contracts\Directive` to require all directives to have an SDL - definition by implementing `public static definition(): string` https://github.com/nuwave/lighthouse/pull/1386 -- Combine `Nuwave\Lighthouse\Schema\Factories\DirectiveNamespacer` and `Nuwave\Lighthouse\Schema\Factories\DirectiveFactory` into - `Lighthouse\Schema\DirectiveLocator` https://github.com/nuwave/lighthouse/pull/1494 +This affects `@orderBy`, `@whereConditions` and `@whereHasConditions` https://github.com/nuwave/lighthouse/pull/1337 +- `__invoke` is now the only supported method name for convention based field resolver classes https://github.com/nuwave/lighthouse/pull/1422 +- Change `Nuwave\Lighthouse\Support\Contracts\Directive` to require all directives to have an SDL definition by implementing `public static definition(): string` https://github.com/nuwave/lighthouse/pull/1386 +- Combine `Nuwave\Lighthouse\Schema\Factories\DirectiveNamespacer` and `Nuwave\Lighthouse\Schema\Factories\DirectiveFactory` into `Lighthouse\Schema\DirectiveLocator` https://github.com/nuwave/lighthouse/pull/1494 - Require `haydenpierce/class-finder` as a built-in dependency https://github.com/nuwave/lighthouse/pull/1494 - Add method `defaultHasOperator` to `Nuwave\Lighthouse\WhereConditions\Operator` https://github.com/nuwave/lighthouse/pull/1412 - Change default configuration options in `lighthouse.php`: @@ -1957,10 +1950,8 @@ You can find and compare releases at the [GitHub release page](https://github.co - `'forceFill' => true` - Use `laragraph/utils` for parsing HTTP requests https://github.com/nuwave/lighthouse/pull/1424 - Replace the subscription broadcast queued event handler with a queued job to allow the queue name to be specified https://github.com/nuwave/lighthouse/pull/1507 -- Make `@method` call the underlying method with the arguments as ordered parameters instead - of the full resolver arguments https://github.com/nuwave/lighthouse/pull/1509 -- Change `ErrorHandler` method `handle()` to non-static `__invoke()` and allow discarding - errors by returning `null` +- Make `@method` call the underlying method with the arguments as ordered parameters instead of the full resolver arguments https://github.com/nuwave/lighthouse/pull/1509 +- Change `ErrorHandler` method `handle()` to non-static `__invoke()` and allow discarding errors by returning `null` - Allow subscriptions without named operations, base channels on the field name - Set `lighthouse.debug` config through env `LIGHTHOUSE_DEBUG` https://github.com/nuwave/lighthouse/pull/1592 - Test helper `multipartGraphQL` now accepts arrays instead of JSON strings https://github.com/nuwave/lighthouse/pull/1615/ @@ -1978,14 +1969,13 @@ You can find and compare releases at the [GitHub release page](https://github.co - Remove interfaces `HasArgumentPath` and `HasErrorBuffer` and the parts of `FieldFactory` that calls them https://github.com/nuwave/lighthouse/pull/1185 - Remove the `ValidationDirective` abstract class in favour of validator classes https://github.com/nuwave/lighthouse/pull/1185 - Remove configuration option `lighthouse.orderBy`, always uses `column` now https://github.com/nuwave/lighthouse/pull/1337 -- Remove `Nuwave\Lighthouse\Support\Contracts\DefinedDirective` interface, moving its - functionality to `Nuwave\Lighthouse\Support\Contracts\Directive` https://github.com/nuwave/lighthouse/pull/1386 +- Remove `Nuwave\Lighthouse\Support\Contracts\DefinedDirective` interface, moving its functionality to `Nuwave\Lighthouse\Support\Contracts\Directive` https://github.com/nuwave/lighthouse/pull/1386 - Remove fallback for `lighthouse.cache.ttl` setting https://github.com/nuwave/lighthouse/pull/1423 - Remove `Nuwave\Lighthouse\Schema\AST\PartialParser` in favor of `GraphQL\Language\Parser` https://github.com/nuwave/lighthouse/pull/1457 - Remove `Nuwave\Lighthouse\Execution\GraphQLRequest` singleton https://github.com/nuwave/lighthouse/pull/1424 - Remove `@bcrypt` in favor of `@hash` https://github.com/nuwave/lighthouse/pull/1200 -- Remove the `@middleware` directive, as it violates the boundary between HTTP and GraphQL - request handling. Use `@guard` or other field middleware directives instead https://github.com/nuwave/lighthouse/pull/1135 +- Remove the `@middleware` directive, as it violates the boundary between HTTP and GraphQL request handling. +Use `@guard` or other field middleware directives instead https://github.com/nuwave/lighthouse/pull/1135 - Remove configuration option `pagination_amount_argument`, it is always `first` now ### Fixed @@ -2032,16 +2022,13 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added - Add artisan command `lighthouse:cache` to compile GraphQL AST https://github.com/nuwave/lighthouse/pull/1451 -- Add middleware `Nuwave\Lighthouse\Support\Http\Middleware\LogGraphQLQueries` that logs every incoming - GraphQL query https://github.com/nuwave/lighthouse/pull/1454 -- Allow custom query validation rules selection by rebinding the interface - `Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules` https://github.com/nuwave/lighthouse/pull/1487 +- Add middleware `Nuwave\Lighthouse\Support\Http\Middleware\LogGraphQLQueries` that logs every incoming GraphQL query https://github.com/nuwave/lighthouse/pull/1454 +- Allow custom query validation rules selection by rebinding the interface `Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules` https://github.com/nuwave/lighthouse/pull/1487 - Add `DateTimeUtc` scalar https://github.com/nuwave/lighthouse/pull/1320 ### Changed -- Publish config file with tag `lighthouse-config` and default schema with tag `lighthouse-schema` - instead of the previously used tags `config` and `schema` https://github.com/nuwave/lighthouse/issues/1489 +- Publish config file with tag `lighthouse-config` and default schema with tag `lighthouse-schema` instead of the previously used tags `config` and `schema` https://github.com/nuwave/lighthouse/issues/1489 - Throw partial errors when failing to delete, forceDelete or restore a model https://github.com/nuwave/lighthouse/pull/1420 - Add `Nuwave\Lighthouse\Execution\ErrorPool` to allow collection of partial errors https://github.com/nuwave/lighthouse/pull/1420 @@ -2065,8 +2052,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Changed - Eager load relationship count in `@count` directive https://github.com/nuwave/lighthouse/pull/1390 -- Simplify the default field resolver classes generated by the artisan commands `lighthouse:query` and `lighthouse:mutation`, - add option `--full` to include the seldom needed resolver arguments `$context` and `$resolveInfo` +- Simplify the default field resolver classes generated by the artisan commands `lighthouse:query` and `lighthouse:mutation`, add option `--full` to include the seldom needed resolver arguments `$context` and `$resolveInfo` ### Fixed @@ -2083,8 +2069,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added -- Write definitions for programmatically registered types to `programmatic-types.graphql` - when running the `lighthouse:ide-helper` artisan command https://github.com/nuwave/lighthouse/pull/1371 +- Write definitions for programmatically registered types to `programmatic-types.graphql` when running the `lighthouse:ide-helper` artisan command https://github.com/nuwave/lighthouse/pull/1371 ### Fixed @@ -2095,8 +2080,8 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Deprecated -- `Nuwave\Lighthouse\Support\Contracts\DefinedDirective::definition()` will be moved to `Nuwave\Lighthouse\Support\Contracts\Directive` - and replace its `name()` method. This requires all directives to have an SDL definition. +- `Nuwave\Lighthouse\Support\Contracts\DefinedDirective::definition()` will be moved to `Nuwave\Lighthouse\Support\Contracts\Directive` and replace its `name()` method. +This requires all directives to have an SDL definition. ## v4.13.1 @@ -2112,8 +2097,7 @@ You can find and compare releases at the [GitHub release page](https://github.co - Add empty root types automatically when extending them https://github.com/nuwave/lighthouse/pull/1347 - Configure a default `guard` for all authentication functionality https://github.com/nuwave/lighthouse/pull/1343 - Configure the default amount of items in paginated lists with `pagination.default_count` https://github.com/nuwave/lighthouse/pull/1352 -- Add new methods `has()`, `overwrite()` and `registerNew()` to `TypeRegistry` to control if types should - be overwritten when registering duplicates https://github.com/nuwave/lighthouse/pull/1361 +- Add new methods `has()`, `overwrite()` and `registerNew()` to `TypeRegistry` to control if types should be overwritten when registering duplicates https://github.com/nuwave/lighthouse/pull/1361 ### Changed @@ -2125,8 +2109,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Deprecated - The setting `paginate_max_count` will change to `pagination.max_count` https://github.com/nuwave/lighthouse/pull/1352 -- The `registerNew()` method of `TypeRegistry` will be removed in favor of `register()`, which will change - its behavior to throw when registering duplicates https://github.com/nuwave/lighthouse/pull/1361 +- The `registerNew()` method of `TypeRegistry` will be removed in favor of `register()`, which will change its behavior to throw when registering duplicates https://github.com/nuwave/lighthouse/pull/1361 ## v4.12.4 @@ -2154,8 +2137,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Fixed -- Fix creating multiple nested BelongsTo relationships on the same level when previous records - with matching attributes exist https://github.com/nuwave/lighthouse/pull/1321 +- Fix creating multiple nested BelongsTo relationships on the same level when previous records with matching attributes exist https://github.com/nuwave/lighthouse/pull/1321 ## v4.12.0 @@ -2172,8 +2154,7 @@ You can find and compare releases at the [GitHub release page](https://github.co - Fix nested mutations with multiple `belongsTo` relations at the same level https://github.com/nuwave/lighthouse/pull/1285 - Avoid race condition that occurs when using `Cache::has()` https://github.com/nuwave/lighthouse/pull/1290 - Replace usage of `resolve()` helper with Lumen-compatible `app()` https://github.com/nuwave/lighthouse/pull/1305 -- Fix using `@create` and `@update` on nested input object fields that accept an array of input types - https://github.com/nuwave/lighthouse/pull/1316 +- Fix using `@create` and `@update` on nested input object fields that accept an array of input types https://github.com/nuwave/lighthouse/pull/1316 ### Changed @@ -2181,16 +2162,14 @@ You can find and compare releases at the [GitHub release page](https://github.co - Improve subscription context serializer https://github.com/nuwave/lighthouse/pull/1283 - Allow replacing the `SubscriptionRegistry` implementation using the container https://github.com/nuwave/lighthouse/pull/1286 - Report errors that are not client-safe through Laravel's `ExceptionHandler` https://github.com/nuwave/lighthouse/pull/1303 -- Log in subscribers when broadcasting a subscription update, so that calls to `auth()->user()` return - the authenticated user instead of `null` https://github.com/nuwave/lighthouse/pull/1306 +- Log in subscribers when broadcasting a subscription update, so that calls to `auth()->user()` return the authenticated user instead of `null` https://github.com/nuwave/lighthouse/pull/1306 - Replace the subscription broadcast queued event handler with a queued job to allow the queue name to be specified https://github.com/nuwave/lighthouse/pull/1301 ## v4.11.0 ### Added -- Add `AttemptAuthentication` middleware to optionally log in users and delegate access guards - to the field level https://github.com/nuwave/lighthouse/pull/1197 +- Add `AttemptAuthentication` middleware to optionally log in users and delegate access guards to the field level https://github.com/nuwave/lighthouse/pull/1197 - Add artisan command `lighthouse:directive` to add directive class https://github.com/nuwave/lighthouse/pull/1240 ### Fixed @@ -2229,50 +2208,40 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Deprecated - Remove `@bcrypt` in favor of `@hash` https://github.com/nuwave/lighthouse/pull/1200 -- `@method` will call the underlying method with the arguments as ordered parameters instead - of the full resolver arguments https://github.com/nuwave/lighthouse/pull/1208 +- `@method` will call the underlying method with the arguments as ordered parameters instead of the full resolver arguments https://github.com/nuwave/lighthouse/pull/1208 ## v4.9.0 ### Added -- Add optional `columnsEnum` argument to the `@whereConditions`, `@whereHasConditions` - and `@orderBy` directives https://github.com/nuwave/lighthouse/pull/1150 -- Exclude or include trashed models in `@can` when `@forceDelete` or `@restore` are used, - the client does not have to filter explicitly https://github.com/nuwave/lighthouse/pull/1157 -- Add test trait `Nuwave\Lighthouse\Testing\MakesGraphQLRequestsLumen` for usage - with Lumen https://github.com/nuwave/lighthouse/pull/1100 -- Add test trait `Nuwave\Lighthouse\Testing\UsesTestSchema` to enable using - a dummy schema for testing custom Lighthouse extensions https://github.com/nuwave/lighthouse/pull/1171 +- Add optional `columnsEnum` argument to the `@whereConditions`, `@whereHasConditions` and `@orderBy` directives https://github.com/nuwave/lighthouse/pull/1150 +- Exclude or include trashed models in `@can` when `@forceDelete` or `@restore` are used, the client does not have to filter explicitly https://github.com/nuwave/lighthouse/pull/1157 +- Add test trait `Nuwave\Lighthouse\Testing\MakesGraphQLRequestsLumen` for usage with Lumen https://github.com/nuwave/lighthouse/pull/1100 +- Add test trait `Nuwave\Lighthouse\Testing\UsesTestSchema` to enable using a dummy schema for testing custom Lighthouse extensions https://github.com/nuwave/lighthouse/pull/1171 - Simplify mocking resolvers that just return static data https://github.com/nuwave/lighthouse/pull/1177 -- Add utility `Nuwave\Lighthouse\ClientDirectives\ClientDirective` to correctly - get the arguments passed through a client directive https://github.com/nuwave/lighthouse/pull/1184 -- Add `streamGraphQL()` helper method to `Nuwave\Lighthouse\Testing\MakesGraphQLRequests` for - simple testing of streamed responses, such as `@defer` https://github.com/nuwave/lighthouse/pull/1184 +- Add utility `Nuwave\Lighthouse\ClientDirectives\ClientDirective` to correctly get the arguments passed through a client directive https://github.com/nuwave/lighthouse/pull/1184 +- Add `streamGraphQL()` helper method to `Nuwave\Lighthouse\Testing\MakesGraphQLRequests` for simple testing of streamed responses, such as `@defer` https://github.com/nuwave/lighthouse/pull/1184 ### Fixed -- Fix eager-loading relations where the parent type is an `interface` or `union` and - may correspond to multiple different models https://github.com/nuwave/lighthouse/pull/1035 +- Fix eager-loading relations where the parent type is an `interface` or `union` and may correspond to multiple different models https://github.com/nuwave/lighthouse/pull/1035 - Fix renaming input fields that are nested within lists using `@rename` https://github.com/nuwave/lighthouse/pull/1166 - Fix handling of nested mutation operations that receive `null` https://github.com/nuwave/lighthouse/pull/1174 - Fix nested mutation `upsert` across two levels of BelongsTo relations https://github.com/nuwave/lighthouse/pull/1169 -- Apply query filters using an `ArgBuilderDirective` such as `@eq` when the argument - is nested deeply within the input https://github.com/nuwave/lighthouse/pull/1176 +- Apply query filters using an `ArgBuilderDirective` such as `@eq` when the argument is nested deeply within the input https://github.com/nuwave/lighthouse/pull/1176 - Fix `Nuwave\Lighthouse\Testing\MakesGraphQLRequestsLumen` test helper https://github.com/nuwave/lighthouse/pull/1186 - Handle multiple instances of client directives with `@defer` correctly https://github.com/nuwave/lighthouse/pull/1184 ### Deprecated -- Deprecate `Nuwave\Lighthouse\Schema\Source\SchemaSourceProvider#setRootPath()`, this function - is never called or used anywhere within Lighthouse. It will be removed from the interface. +- Deprecate `Nuwave\Lighthouse\Schema\Source\SchemaSourceProvider#setRootPath()`, this function is never called or used anywhere within Lighthouse. +It will be removed from the interface. ## v4.8.1 ### Fixed -- Avoid erasing the model information from the wrapping paginated results `type` when defining - a paginated `@hasMany` field after a field with `@paginate` https://github.com/nuwave/lighthouse/pull/1149 +- Avoid erasing the model information from the wrapping paginated results `type` when defining a paginated `@hasMany` field after a field with `@paginate` https://github.com/nuwave/lighthouse/pull/1149 ## v4.8.0 @@ -2280,44 +2249,35 @@ You can find and compare releases at the [GitHub release page](https://github.co - Compose complex input arguments through nested arg resolvers https://github.com/nuwave/lighthouse/pull/899 - Add `Nuwave\Lighthouse\Support\Contracts\ArgResolver` directive interface https://github.com/nuwave/lighthouse/pull/899 -- Allow existing mutation directives `@create`, `@update`, `@upsert` and `@delete` to function - as nested arg resolvers https://github.com/nuwave/lighthouse/pull/899 +- Allow existing mutation directives `@create`, `@update`, `@upsert` and `@delete` to function as nested arg resolvers https://github.com/nuwave/lighthouse/pull/899 - Validate at schema build time that the `apply` argument `@rules` is an array https://github.com/nuwave/lighthouse/pull/1092 - Add support in `@whereConditions` for IN, IS NULL and BETWEEN operators https://github.com/nuwave/lighthouse/pull/1099 -- Add ability to define pivot data on nested mutations within `sync`, `syncWithoutDetaching` - and `connect` https://github.com/nuwave/lighthouse/pull/1110 -- Allow restricting the columns for `@orderBy` to a given whitelist and generate - an `enum` definition for it https://github.com/nuwave/lighthouse/pull/1118 +- Add ability to define pivot data on nested mutations within `sync`, `syncWithoutDetaching` and `connect` https://github.com/nuwave/lighthouse/pull/1110 +- Allow restricting the columns for `@orderBy` to a given whitelist and generate an `enum` definition for it https://github.com/nuwave/lighthouse/pull/1118 - Allow passing variables in `->graphQL()` test helper https://github.com/nuwave/lighthouse/pull/1127 - Add missing schema descriptions to some inputs, types, and enums https://github.com/nuwave/lighthouse/pull/1131 - Add `@guard` directive to handle authentication https://github.com/nuwave/lighthouse/pull/1135 -- Add `@whereHasConditions` directive to filter query results based on the existence - of a relationship https://github.com/nuwave/lighthouse/pull/1140 +- Add `@whereHasConditions` directive to filter query results based on the existence of a relationship https://github.com/nuwave/lighthouse/pull/1140 ### Changed -- Remove `Nuwave\Lighthouse\Execution\MutationExecutor` in favor of modular - nested arg resolvers https://github.com/nuwave/lighthouse/pull/899 -- Register the operator enum for `@whereConditions` programmatically and allow - overwriting it through a service provider https://github.com/nuwave/lighthouse/pull/1099 -- Always automatically set the correct argument type when using `@whereConditions` or `@orderBy` - directives https://github.com/nuwave/lighthouse/pull/1118 +- Remove `Nuwave\Lighthouse\Execution\MutationExecutor` in favor of modular nested arg resolvers https://github.com/nuwave/lighthouse/pull/899 +- Register the operator enum for `@whereConditions` programmatically and allow overwriting it through a service provider https://github.com/nuwave/lighthouse/pull/1099 +- Always automatically set the correct argument type when using `@whereConditions` or `@orderBy` directives https://github.com/nuwave/lighthouse/pull/1118 - Implement the `name()` function generically in the BaseDirective class https://github.com/nuwave/lighthouse/pull/1098 - Renamed the `@whereConstraints` directive to `@whereConditions` https://github.com/nuwave/lighthouse/pull/1140 ### Fixed -- Enable chained rule provider directives (`ProvidesRules`) to merge the rules - before validating https://github.com/nuwave/lighthouse/pull/1082 +- Enable chained rule provider directives (`ProvidesRules`) to merge the rules before validating https://github.com/nuwave/lighthouse/pull/1082 - Apply nested `OR` conditions in `@whereConditions` correctly https://github.com/nuwave/lighthouse/pull/1099 - Allow passing `null` or simply no `id` when using `@upsert` https://github.com/nuwave/lighthouse/pull/1114 ### Deprecated -- The argument `field` within the `OrderByClause` used for `@orderBy` will be renamed to `column` - in v5 https://github.com/nuwave/lighthouse/pull/1118 -- Deprecated the `@middleware` directive, as it violates the boundary between HTTP and GraphQL - request handling. Use `@guard` or other field middleware directives instead https://github.com/nuwave/lighthouse/pull/1135 +- The argument `field` within the `OrderByClause` used for `@orderBy` will be renamed to `column` in v5 https://github.com/nuwave/lighthouse/pull/1118 +- Deprecated the `@middleware` directive, as it violates the boundary between HTTP and GraphQL request handling. +Use `@guard` or other field middleware directives instead https://github.com/nuwave/lighthouse/pull/1135 ### Removed @@ -2327,8 +2287,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Fixed -- Enable multiple queries in a single request by clearing `BatchLoader` instances - after executing each query https://github.com/nuwave/lighthouse/pull/1030 +- Enable multiple queries in a single request by clearing `BatchLoader` instances after executing each query https://github.com/nuwave/lighthouse/pull/1030 - Keep the query and pagination capabilities of relation directives when disabling batch loading https://github.com/nuwave/lighthouse/pull/1083 ## v4.7.1 @@ -2339,25 +2298,21 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Fixed -- Define `@enum` as a directive class so it shows up in `schema-directives.graphql` - and can potentially be overwritten https://github.com/nuwave/lighthouse/pull/1078 +- Define `@enum` as a directive class so it shows up in `schema-directives.graphql` and can potentially be overwritten https://github.com/nuwave/lighthouse/pull/1078 ## v4.7.0 ### Added - Add `syncWithoutDetaching` option for BelongsToMany and MorphToMany relationships https://github.com/nuwave/lighthouse/pull/1031 -- Add `injectArgs` option to `@can` directive to pass along client defined - arguments to the policy check https://github.com/nuwave/lighthouse/pull/1043 -- Allow globally turning off relation batch loading through the - config option `batchload_relations` https://github.com/nuwave/lighthouse/pull/1059 +- Add `injectArgs` option to `@can` directive to pass along client defined arguments to the policy check https://github.com/nuwave/lighthouse/pull/1043 +- Allow globally turning off relation batch loading through the config option `batchload_relations` https://github.com/nuwave/lighthouse/pull/1059 - Add `Nuwave\Lighthouse\Execution\DataLoader\BatchLoader#loadMany()` function https://github.com/nuwave/lighthouse/pull/973 - Extend `@rename` directive to work with arguments and input fields https://github.com/nuwave/lighthouse/issues/521 ### Changed -- Add ability to fetch soft deleted model within `@can` directive to validate permissions - using `@softDeletes` directive. https://github.com/nuwave/lighthouse/pull/1042 +- Add ability to fetch soft deleted model within `@can` directive to validate permissions using `@softDeletes` directive. https://github.com/nuwave/lighthouse/pull/1042 - Improve the error message for missing field resolvers by offering a solution https://github.com/nuwave/lighthouse/pull/1045 - Throw `DefinitionException` when missing a type in the type registry https://github.com/nuwave/lighthouse/pull/1066 - Add `INPUT_FIELD_DEFINITION` to `orderBy` directive location https://github.com/nuwave/lighthouse/pull/1069 @@ -2398,8 +2353,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added -- Add `@upsert` directive and nested mutation operations to create or update a model - regardless whether it exists https://github.com/nuwave/lighthouse/pull/1005 +- Add `@upsert` directive and nested mutation operations to create or update a model regardless whether it exists https://github.com/nuwave/lighthouse/pull/1005 ### Fixed @@ -2409,20 +2363,17 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added -- Validate the correctness of the `builder` given to `@paginate` at schema - build time +- Validate the correctness of the `builder` given to `@paginate` at schema build time ### Fixed -- Do not require the type of a field matching a model class when using the - `builder` argument of `@paginate` https://github.com/nuwave/lighthouse/pull/1011 +- Do not require the type of a field matching a model class when using the `builder` argument of `@paginate` https://github.com/nuwave/lighthouse/pull/1011 ## v4.4.1 ### Fixed -- Fix regression in 4.4.0 that required matching the type returned from paginated relationship - fields with the class name of the model https://github.com/nuwave/lighthouse/pull/1011 +- Fix regression in 4.4.0 that required matching the type returned from paginated relationship fields with the class name of the model https://github.com/nuwave/lighthouse/pull/1011 ## v4.4.0 @@ -2431,14 +2382,12 @@ You can find and compare releases at the [GitHub release page](https://github.co - Add `@count` directive for counting a relationship https://github.com/nuwave/lighthouse/pull/984 - Allow overwriting the name of Enum types created through `LaravelEnumType` https://github.com/nuwave/lighthouse/pull/968 - Resolve models through Relay's global identification using `@node` https://github.com/nuwave/lighthouse/pull/974 -- Add experimental `@modelClass` directive to map types to models. It will be renamed - to `@model` in v5 https://github.com/nuwave/lighthouse/pull/974 +- Add experimental `@modelClass` directive to map types to models. It will be renamed to `@model` in v5 https://github.com/nuwave/lighthouse/pull/974 ### Fixed - Remove the extra new line from the returned value when using `@globalId(decode: "ID")` https://github.com/nuwave/lighthouse/pull/982 -- Throw a syntax error instead of an exception when performing an - empty request or a request with an empty query https://github.com/nuwave/lighthouse/pull/989 +- Throw a syntax error instead of an exception when performing an empty request or a request with an empty query https://github.com/nuwave/lighthouse/pull/989 - Properly apply `@spread` when used within a nested input object https://github.com/nuwave/lighthouse/pull/992 ### Changed @@ -2460,8 +2409,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added - Add `@restore` and `@forceDelete` directives, similar to `@delete` https://github.com/nuwave/lighthouse/pull/941 -- Add `@softDeletes` and `@trashed` directives to enable - filtering soft deleted models https://github.com/nuwave/lighthouse/pull/937 +- Add `@softDeletes` and `@trashed` directives to enable filtering soft deleted models https://github.com/nuwave/lighthouse/pull/937 ### Fixed @@ -2469,8 +2417,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Changed -- Validate requirements for argument definitions of `@delete`, `@forceDelete` and `@restore` - during schema build time https://github.com/nuwave/lighthouse/pull/941 +- Validate requirements for argument definitions of `@delete`, `@forceDelete` and `@restore` during schema build time https://github.com/nuwave/lighthouse/pull/941 ## v4.2.1 @@ -2498,13 +2445,9 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added -- Add the `@whereJsonContains` directive to an input value as - a [whereJsonContains filter -- Allow using callable classes with `__invoke` when referencing methods in directives - and when looking for default resolvers or type resolvers https://github.com/nuwave/lighthouse/issues/882 -- Allow to restrict column names to a well-defined list in `@whereContraints` - and generate definitions for an `Enum` type and an `Input` type - that are restricted to the defined columns https://github.com/nuwave/lighthouse/pull/916 +- Add the `@whereJsonContains` directive to an input value as a whereJsonContains filter +- Allow using callable classes with `__invoke` when referencing methods in directives and when looking for default resolvers or type resolvers https://github.com/nuwave/lighthouse/issues/882 +- Allow to restrict column names to a well-defined list in `@whereContraints` and generate definitions for an `Enum` type and an `Input` type that are restricted to the defined columns https://github.com/nuwave/lighthouse/pull/916 - Add test helpers for introspection queries to `MakesGraphQLRequests` https://github.com/nuwave/lighthouse/pull/916 ### Deprecated @@ -2521,8 +2464,7 @@ You can find and compare releases at the [GitHub release page](https://github.co - Add the `@namespace` directive as a replacement for the removed `@group` directive https://github.com/nuwave/lighthouse/pull/768 - The `@defer` extension now supports deferring nested fields of mutations https://github.com/nuwave/lighthouse/pull/855 -- Add a simple way to define complex validation directives by - extending `Nuwave\Lighthouse\Schema\Directives\ValidationDirective` https://github.com/nuwave/lighthouse/pull/846 +- Add a simple way to define complex validation directives by extending `Nuwave\Lighthouse\Schema\Directives\ValidationDirective` https://github.com/nuwave/lighthouse/pull/846 - Extend the `@belongsToMany` directive to support pivot data on a custom Relay style Edge type https://github.com/nuwave/lighthouse/pull/871 - Implement `connect`, `disconnect` and `delete` operations for nested mutations upon MorphTo relationships https://github.com/nuwave/lighthouse/pull/879 @@ -2538,32 +2480,24 @@ You can find and compare releases at the [GitHub release page](https://github.co - Fix handling of `@include` directive, it is semantically opposite to `@skip`, when using it with `@defer` https://github.com/nuwave/lighthouse/pull/855 - Allow querying for null values using `@whereConstraints` https://github.com/nuwave/lighthouse/pull/872 - Fix issue when using the `@model` directive in a type that has a list field https://github.com/nuwave/lighthouse/pull/883 -- Make the `@include` and `@skip` directives that are part of the GraphQL spec show up in introspection - and fix handling of default values in custom client directives https://github.com/nuwave/lighthouse/pull/892 +- Make the `@include` and `@skip` directives that are part of the GraphQL spec show up in introspection and fix handling of default values in custom client directives https://github.com/nuwave/lighthouse/pull/892 ### Changed - Bumped the requirement on `webonyx/graphql-php` to `^0.13.2` https://github.com/nuwave/lighthouse/pull/768 - Rename directive interfaces dealing with types from `Node*` to `Type*` https://github.com/nuwave/lighthouse/pull/768 -- Change the signature of the AST manipulating directive interfaces: - `TypeManipulator`, `FieldManipulator` and `ArgManipulator` https://github.com/nuwave/lighthouse/pull/768 +- Change the signature of the AST manipulating directive interfaces: `TypeManipulator`, `FieldManipulator` and `ArgManipulator` https://github.com/nuwave/lighthouse/pull/768 - Change the API of the `DocumentAST` class to enable a more performant implementation https://github.com/nuwave/lighthouse/pull/768 - Enable the schema caching option `lighthouse.cache.enable` by default https://github.com/nuwave/lighthouse/pull/768 -- Lazily load types from the schema. Directives defined on parts of the schema that are not used within the current - query are no longer run on every request https://github.com/nuwave/lighthouse/pull/768 -- Simplify the default route configuration. - Make sure to review your `config/lighthouse.php` and bring it up to date - with the latest changes in the base configuration file https://github.com/nuwave/lighthouse/pull/820 +- Lazily load types from the schema. Directives defined on parts of the schema that are not used within the current query are no longer run on every request https://github.com/nuwave/lighthouse/pull/768 +- Simplify the default route configuration. Make sure to review your `config/lighthouse.php` and bring it up to date with the latest changes in the base configuration file https://github.com/nuwave/lighthouse/pull/820 - Move `SubscriptionExceptionHandler` into namespace `Nuwave\Lighthouse\Subscriptions\Contracts` https://github.com/nuwave/lighthouse/pull/819 -- The pagination field argument that controls the amount of results - now defaults to `first` instead of `count`. The config `pagination_amount_argument` - can be used to change the argument name https://github.com/nuwave/lighthouse/pull/852 +- The pagination field argument that controls the amount of results now defaults to `first` instead of `count`. +The config `pagination_amount_argument` can be used to change the argument name https://github.com/nuwave/lighthouse/pull/852 - Rename `ArgValidationDirective` to `ProvidesRules` and drop `get` prefix from the methods within https://github.com/nuwave/lighthouse/pull/846 - Make the argument used for finding a model to check `@can` against configurable. - The previous behavior of implicitly using the `id` argument for finding a specific - model to authorize against now no longer works. https://github.com/nuwave/lighthouse/pull/856 -- Change the `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` wrapper to map - to Enum instances internally https://github.com/nuwave/lighthouse/pull/908 +The previous behavior of implicitly using the `id` argument for finding a specific model to authorize against now no longer works. https://github.com/nuwave/lighthouse/pull/856 +- Change the `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` wrapper to map to Enum instances internally https://github.com/nuwave/lighthouse/pull/908 ### Removed @@ -2592,8 +2526,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Fixed - Fix querying for falsy values through `@whereConstraints` https://github.com/nuwave/lighthouse/pull/800 -- Use `Illuminate\Contracts\Events\Dispatcher` instead of concrete implementation - in SubscriptionBroadcaster https://github.com/nuwave/lighthouse/pull/805 +- Use `Illuminate\Contracts\Events\Dispatcher` instead of concrete implementation in SubscriptionBroadcaster https://github.com/nuwave/lighthouse/pull/805 ### Deprecated @@ -2610,8 +2543,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Added - Add `@whereConstraints` directive that offers flexible query capabilities to the client https://github.com/nuwave/lighthouse/pull/753 -- Add convenience wrapper for registering Enum types based on [BenSampo/laravel-enum - https://github.com/nuwave/lighthouse/pull/779 +- Add convenience wrapper for registering Enum types based on BenSampo/laravel-enum https://github.com/nuwave/lighthouse/pull/779 ### Deprecated @@ -2627,8 +2559,7 @@ You can find and compare releases at the [GitHub release page](https://github.co ### Fixed -- You can now omit an `input` argument from a query that uses - the `@spread` directive without getting an error https://github.com/nuwave/lighthouse/pull/774 +- You can now omit an `input` argument from a query that uses the `@spread` directive without getting an error https://github.com/nuwave/lighthouse/pull/774 ### Deprecated @@ -2646,21 +2577,17 @@ You can find and compare releases at the [GitHub release page](https://github.co - Default the config to always set the `Accept: application/json` header https://github.com/nuwave/lighthouse/pull/743 - Declare a single named route which handles POST/GET instead of 2 separate routes https://github.com/nuwave/lighthouse/pull/738 -- Apply the nested operations within a nested mutation in a consistent order - that makes sense https://github.com/nuwave/lighthouse/pull/754 +- Apply the nested operations within a nested mutation in a consistent order that makes sense https://github.com/nuwave/lighthouse/pull/754 ### Deprecated -- The pagination field argument that controls the amount of results - will default to `first` instead of `count` in v4. The config `pagination_amount_argument` - can be used to change the argument name now https://github.com/nuwave/lighthouse/pull/752 +- The pagination field argument that controls the amount of results will default to `first` instead of `count` in v4. +The config `pagination_amount_argument` can be used to change the argument name now https://github.com/nuwave/lighthouse/pull/752 ### Fixed -- Instantiate the `ErrorBuffer` directly, its dependencies - can not be resolved through the container https://github.com/nuwave/lighthouse/pull/756 -- Refresh `GraphQLRequest` singleton between multiple requests to prevent - a common error in test execution https://github.com/nuwave/lighthouse/pull/761 +- Instantiate the `ErrorBuffer` directly, its dependencies can not be resolved through the container https://github.com/nuwave/lighthouse/pull/756 +- Refresh `GraphQLRequest` singleton between multiple requests to prevent a common error in test execution https://github.com/nuwave/lighthouse/pull/761 ## v3.4.0 @@ -2674,16 +2601,14 @@ You can find and compare releases at the [GitHub release page](https://github.co - Sync existing models in belongsToMany relations using nested mutations when creating https://github.com/nuwave/lighthouse/pull/707 - Add `@spread` directive to reshape nested input arguments https://github.com/nuwave/lighthouse/pull/680 -- Add flexible `@builder` directive to quickly specify a single method to apply constraints - to the query builder https://github.com/nuwave/lighthouse/pull/680 +- Add flexible `@builder` directive to quickly specify a single method to apply constraints to the query builder https://github.com/nuwave/lighthouse/pull/680 - Add `new_between_directives` config to use the new between directives now https://github.com/nuwave/lighthouse/pull/680 ### Deprecated - Use the `@spread` instead of the `flatten` argument of `@create`/`@update` https://github.com/nuwave/lighthouse/pull/680 - Prefer usage of the `ArgBuilderDirective` instead of the `ArgFilterDirective` https://github.com/nuwave/lighthouse/pull/680 -- `@whereBetween` and `@whereNotBetween` will take a single input object - instead of being spread across two args https://github.com/nuwave/lighthouse/pull/680 +- `@whereBetween` and `@whereNotBetween` will take a single input object instead of being spread across two args https://github.com/nuwave/lighthouse/pull/680 ## v3.2.1 @@ -2714,8 +2639,7 @@ You can find and compare releases at the [GitHub release page](https://github.co - Support Subscriptions https://github.com/nuwave/lighthouse/pull/337 - Support `@defer` client directive https://github.com/nuwave/lighthouse/pull/422 - Define validation for list arguments themselves through `@rulesForArray` https://github.com/nuwave/lighthouse/pull/427 -- The `@hasMany` and `@paginator` directives now support an additional argument `defaultCount` - that sets a default value for the generated field argument `count` https://github.com/nuwave/lighthouse/pull/428 +- The `@hasMany` and `@paginator` directives now support an additional argument `defaultCount` that sets a default value for the generated field argument `count` https://github.com/nuwave/lighthouse/pull/428 - Allow user to be guest when using the `@can` directive https://github.com/nuwave/lighthouse/pull/431 - Add shortcut to get NodeValue type definition fields https://github.com/nuwave/lighthouse/pull/432 - Use `@inject` with dot notation to set nested value https://github.com/nuwave/lighthouse/pull/511 @@ -2735,11 +2659,9 @@ You can find and compare releases at the [GitHub release page](https://github.co - Change the default schema location, model and GraphQL namespaces https://github.com/nuwave/lighthouse/pull/423 - Construction and methods of the Field|Node|Arg-Value objects https://github.com/nuwave/lighthouse/pull/425 -- The methods called with `@method` now receive the same 4 resolver arguments that all - other resolvers do https://github.com/nuwave/lighthouse/pull/486 +- The methods called with `@method` now receive the same 4 resolver arguments that all other resolvers do https://github.com/nuwave/lighthouse/pull/486 - Handle mutating directives transactional by default https://github.com/nuwave/lighthouse/pull/512 -- Nested mutations for BelongsTo require wrapping the ID in a - `connect` argument https://github.com/nuwave/lighthouse/pull/514 https://github.com/nuwave/lighthouse/pull/549 +- Nested mutations for BelongsTo require wrapping the ID in a `connect` argument https://github.com/nuwave/lighthouse/pull/514 https://github.com/nuwave/lighthouse/pull/549 - Make the error messages returned by `@can` more friendly https://github.com/nuwave/lighthouse/pull/515 - Bump requirements for `webonyx/graphql-php` to `^0.13` and PHP to `>= 7.1` https://github.com/nuwave/lighthouse/pull/517 - Replace `DirectiveRegistry` with `DirectiveFactory` to lazy load directives https://github.com/nuwave/lighthouse/pull/520 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a643707f2c..c7639a6f3f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,8 +25,10 @@ Before you release a new version, make sure to familiarize yourself with: - [Previous GitHub Releases](https://github.com/nuwave/lighthouse/releases) To create a new release, follow these steps: -1. Consider the entries in the [`CHANGELOG unreleased section`](CHANGELOG.md#unreleased), add missing entries if needed -2. Based on those entries and the previous version, define the next version number and add it to the [`CHANGELOG.md`](CHANGELOG.md) +1. Consider the entries in the [`CHANGELOG unreleased section`](CHANGELOG.md#unreleased). +Add missing entries if needed. +2. Based on those entries and the previous version, define the next version number. +Add it to [`CHANGELOG.md`](CHANGELOG.md). 3. [Draft a new release](https://github.com/nuwave/lighthouse/releases/new) 4. Add the version number as both tag and title 5. Add the changelog entries as the description @@ -85,7 +87,8 @@ Have a new feature? You can start off by writing some tests that detail the behavior you want to achieve and go from there. Fixing a bug? -The best way to ensure it is fixed for good and never comes back is to write a failing test for it and then make it pass. +The best way to ensure it is fixed for good is to write a failing test. +Then make it pass so it does not come back. If you cannot figure out how to fix it yourself, feel free to submit a PR with a failing test. Here is how to set up Xdebug in PhpStorm: https://www.jetbrains.com/help/phpstorm/configuring-xdebug.html. @@ -93,7 +96,7 @@ Here is how to set up Xdebug in PhpStorm: https://www.jetbrains.com/help/phpstor > Enabling Xdebug slows down tests by an order of magnitude. > Stop listening for Debug Connection to speed it back up. -Set the environment variable `XDEBUG_REMOTE_HOST` to the IP of your host machine as seen from the Docker container. +Set the environment variable `XDEBUG_REMOTE_HOST` to your host machine IP as seen from the Docker container. This may differ based on your setup. When running Docker for Desktop, it is usually `10.0.2.2`, when running from a VM it is something else. @@ -205,8 +208,8 @@ Prefer direct usage of Illuminate classes instead of helpers. +Arr::get($foo, 'bar'); ``` -A notable exception is the `response()` helper - using DI for injecting a -`ResponseFactory` does not work in Lumen, while `response()` works for both. +A notable exception is the `response()` helper. +Using DI for injecting a `ResponseFactory` does not work in Lumen, while `response()` works for both. ### Type Definitions @@ -223,9 +226,8 @@ If known, add additional type information in the PHPDoc. function foo(array $bar): string ``` -For aggregate types such as the commonly used `Collection` class, use -the generic type hint style. While not officially part of PHPDoc, it is understood -by PhpStorm and most other editors. +For aggregate types such as the commonly used `Collection` class, use the generic type hint style. +While not officially part of PHPDoc, it is understood by PhpStorm and most other editors. ```php /** @@ -237,9 +239,7 @@ function foo(): Collection ``` Use `self` to annotate that a class returns an instance of itself (or its child). -Use [PHPDoc type hints](https://docs.phpdoc.org/guides/types.html#keywords) to -differentiate between cases where you return the original object instance and -other cases where you instantiate a new class. +Use [PHPDoc type hints](https://docs.phpdoc.org/guides/types.html#keywords) to differentiate between cases where you return the original object instance and other cases where you instantiate a new class. ```php class Foo @@ -276,6 +276,24 @@ class Foo } ``` +### Prose Formatting + +Use [Semantic Line Breaks](https://sembr.org) for prose in markdown files and multiline code comments. + +Write one sentence per line by default, instead of wrapping at a fixed column width. +Do not split a sentence across lines at commas or clauses. +If a sentence becomes too long, rewrite it into multiple shorter sentences. +Keep rendered output unchanged. + +Apply this style to edited prose in: +- `*.md` files +- multiline prose comments and PHPDoc blocks + +Do not reflow: +- code blocks and snippets +- PHPDoc tags (for example `@param`, `@return`, `@throws`) +- generated files + ## Code Style We format the code automatically with [php-cs-fixer](https://github.com/friendsofphp/php-cs-fixer). diff --git a/README.md b/README.md index 356c24d87f..249fe7b529 100644 --- a/README.md +++ b/README.md @@ -21,16 +21,15 @@ Lighthouse is a GraphQL framework that integrates with your Laravel application. -It takes the best ideas of both and combines them to solve common tasks with ease -and offer flexibility when you need it. +It combines the best ideas of both ecosystems. +It solves common tasks with ease and offers flexibility when you need it. ## Documentation The documentation lives at [lighthouse-php.com](https://lighthouse-php.com). The site includes the latest docs for each major version of Lighthouse. -You can find docs for specific versions by looking at the contents of [/docs/master](/docs/master) -at that point in the git history: `https://github.com/nuwave/lighthouse/tree//docs/master`. +You can find docs for specific versions by looking at the contents of [/docs/master](/docs/master) at that point in the git history: `https://github.com/nuwave/lighthouse/tree//docs/master`. ## Get Involved @@ -46,10 +45,10 @@ Lighthouse follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Only the current major version receives new features and bugfixes. -Updating between minor versions will not require changes to PHP code or the GraphQL schema -and cause no breaking behavioral changes for consumers of the GraphQL API. -However, only code elements marked with `@api` will remain compatible - all other code in -Lighthouse is considered internal and is thus subject to change. +Updating between minor versions does not require changes to PHP code or the GraphQL schema. +It also causes no breaking behavioral changes for consumers of the GraphQL API. +However, only code elements marked with `@api` remain compatible. +All other code in Lighthouse is internal and subject to change. ## Changelog @@ -65,8 +64,7 @@ We welcome contributions of any kind, see how in [`CONTRIBUTING.md`](CONTRIBUTIN ## Security Vulnerabilities -If you discover a security vulnerability within Lighthouse, -please email Benedikt Franke via [benedikt@franke.tech](mailto:benedikt@franke.tech). +If you discover a security vulnerability within Lighthouse, email Benedikt Franke at [benedikt@franke.tech](mailto:benedikt@franke.tech). ## Sponsors diff --git a/UPGRADE.md b/UPGRADE.md index a278f79883..17f4330320 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -14,9 +14,9 @@ Compare your `lighthouse.php` against the latest [default configuration](src/lig Methods you need to explicitly call to set up test traits were removed in favor of automatic setup. - Remove calls to `Nuwave\Lighthouse\Testing\RefreshesSchemaCache::bootRefreshesSchemaCache()`. - This only works when your test class uses the trait `Nuwave\Lighthouse\Testing\MakesGraphQLRequests`. +This only works when your test class uses the trait `Nuwave\Lighthouse\Testing\MakesGraphQLRequests`. - Replace calls to `Nuwave\Lighthouse\Testing\MakesGraphQLRequests::setUpSubscriptionEnvironment()` with ` use Nuwave\Lighthouse\Testing\TestsSubscriptions`. - This only works when your test class extends `Illuminate\Foundation\Testing\TestCase`. +This only works when your test class extends `Illuminate\Foundation\Testing\TestCase`. ### `EnsureXHR` is enabled in the default configuration @@ -68,9 +68,9 @@ The Artisan command `lighthouse:clear-cache` was renamed to `lighthouse:clear-sc ### `messages` on `@rules` and `@rulesForArray` -Lighthouse previously allowed passing a map with arbitrary keys as the `messages` -argument of `@rules` and `@rulesForArray`. Such a construct is impossible to define -within the directive definition and leads to static validation errors. +Lighthouse previously allowed passing a map with arbitrary keys as the `messages` argument of `@rules` and `@rulesForArray`. +This construct is impossible to define within the directive definition. +It leads to static validation errors. ```diff @rules( @@ -89,8 +89,9 @@ within the directive definition and leads to static validation errors. ### Use filters in `@delete`, `@forceDelete` and `@restore` -Whereas previously, those directives enforced the usage of a single argument and assumed that -to be the ID or list of IDs of the models to modify, they now leverage argument filter directives. +Previously, those directives enforced a single argument. +They assumed that argument was the ID or list of IDs of models to modify. +They now leverage argument filter directives. This brings them in line with other directives such as `@find` and `@all`. You will need to explicitly add `@whereKey` to the argument that contained the ID or IDs. @@ -106,8 +107,8 @@ type Mutation { ### Use `@globalId` over `@delete(globalId: true)` -The `@delete`, `@forceDelete`, `@restore` and `@upsert` directives no longer offer the -`globalId` argument. Use `@globalId` on the argument instead. +The `@delete`, `@forceDelete`, `@restore` and `@upsert` directives no longer offer the `globalId` argument. +Use `@globalId` on the argument instead. ```diff type Mutation { @@ -118,8 +119,7 @@ type Mutation { ### Specify `@guard(with: "api")` as `@guard(with: ["api"])` -Due to Lighthouse's ongoing effort to provide static schema validation, -the `with` argument of `@guard` must now be provided as a list of strings. +Due to Lighthouse's ongoing effort to provide static schema validation, the `with` argument of `@guard` must now be a list of strings. ```diff type Mutation { @@ -148,43 +148,40 @@ The previous version 1 contained a redundant key `channels` and is no longer sup } ``` -It is recommended to switch to version 2 before upgrading Lighthouse to give clients -a smooth transition period. +Switch to version 2 before upgrading Lighthouse. +This gives clients a smooth transition period. ### Nullability of pagination results Generated result types of paginated lists are now always marked as non-nullable. The setting `non_null_pagination_results` was removed and now always behaves as if it were `true`. -This is generally more convenient for clients, but will -cause validation errors to bubble further up in the result. +This is generally more convenient for clients. +It causes validation errors to bubble further up in the result. ### Nullability of pagination `first` -Previously, the pagination argument `first` was either marked as non-nullable, -or non-nullable with a default value. +Previously, the pagination argument `first` was either non-nullable or non-nullable with a default value. Now, it will always be marked as non-nullable, regardless if it has a default or not. This prevents clients from passing an invalid explicit `null`. ### Complexity calculation -Prior to `v6`, overwriting the default query complexity calculation on paginated fields -required the usage of `@complexity` without any arguments. Now, `@paginate` performs that -calculation by default - with the additional change that it also includes the cost of the -field itself, adding a value of `1` to represent the complexity more accurately. +Prior to `v6`, overwriting the default query complexity calculation on paginated fields required `@complexity` without arguments. +Now, `@paginate` performs that calculation by default. +It also includes the cost of the field itself, adding a value of `1` for a more accurate complexity score. Using `@complexity` without the `resolver` argument is now no longer supported. ### Passing of `BenSampo\Enum\Enum` instances to `ArgBuilderDirective::handleBuilder()` -Prior to `v6`, Lighthouse would extract the internal `$value` from instances of -`BenSampo\Enum\Enum` before passing it to `ArgBuilderDirective::handleBuilder()` -if the setting `unbox_bensampo_enum_enum_instances` was `true`. +Prior to `v6`, Lighthouse extracted the internal `$value` from `BenSampo\Enum\Enum` instances before passing it to `ArgBuilderDirective::handleBuilder()`. +This happened if `unbox_bensampo_enum_enum_instances` was `true`. -This is generally unnecessary, because Laravel automagically calls the Enum's `__toString()` -method when using it in a query. This might affect users who use an `ArgBuilderDirective` -that delegates to a method that relies on an internal value being passed. +This is generally unnecessary. +Laravel automatically calls the Enum `__toString()` method when using it in a query. +This might affect users whose `ArgBuilderDirective` delegates to a method that relies on an internal value. ```graphql type Query { @@ -200,8 +197,9 @@ public function scopeByType(Builder $builder, int $aOrB): Builder } ``` -In the future, Lighthouse will pass the actual Enum instance along. You can opt in to -the new behavior before upgrading by setting `unbox_bensampo_enum_enum_instances` to `false`. +In the future, Lighthouse will pass the actual Enum instance along. +You can opt in to the new behavior before upgrading. +Set `unbox_bensampo_enum_enum_instances` to `false`. ```php public function scopeByType(Builder $builder, AOrB $aOrB): Builder @@ -295,21 +293,18 @@ function (mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolv ### Replace `Nuwave\Lighthouse\GraphQL::executeQuery()` usage -Use `executeQueryString()` for executing a string query or `executeParsedQuery()` for -executing an already parsed `DocumentNode` instance. +Use `executeQueryString()` for executing a string query or `executeParsedQuery()` for executing an already parsed `DocumentNode` instance. ### Removed error extension field `category` See https://github.com/webonyx/graphql-php/blob/master/UPGRADE.md#breaking-removed-error-extension-field-category. -You can [leverage `GraphQL\Error\ProvidesExtensions`](https://lighthouse-php.com/master/digging-deeper/error-handling.html#additional-error-information) -to restore `category` in your custom exceptions. Additionally, you may [implement a custom error handler](https://lighthouse-php.com/master/digging-deeper/error-handling.html#registering-error-handlers) -that wraps well-known third-party exceptions with your own exception that adds an appropriate `category`. +You can [leverage `GraphQL\Error\ProvidesExtensions`](https://lighthouse-php.com/master/digging-deeper/error-handling.html#additional-error-information) to restore `category` in your custom exceptions. +Additionally, you may [implement a custom error handler](https://lighthouse-php.com/master/digging-deeper/error-handling.html#registering-error-handlers) that wraps well-known third-party exceptions with your own exception that adds an appropriate `category`. ### Use native interface for errors with extensions -Use `GraphQL\Error\ProvidesExtensions::getExtensions()` over `Nuwave\Lighthouse\Exceptions\RendersErrorsExtensions::extensionsContent()` -to return extra information from exceptions: +Use `GraphQL\Error\ProvidesExtensions::getExtensions()` over `Nuwave\Lighthouse\Exceptions\RendersErrorsExtensions::extensionsContent()` to return extra information from exceptions: ```diff use Exception; @@ -350,18 +345,15 @@ abstract class TestCase extends BaseTestCase ### Schema caching v1 removal -Schema caching now uses v2 only. That means, the schema cache will be -written to a php file that OPcache will pick up instead of being written -to the configured cache driver. This significantly reduces memory usage. +Schema caching now uses v2 only. +That means, the schema cache will be written to a php file that OPcache will pick up instead of being written to the configured cache driver. +This significantly reduces memory usage. -If you had previously depended on the presence of the schema in your -cache, then you will need to change your code. +If you had previously depended on the presence of the schema in your cache, then you will need to change your code. ### Register `ScoutServiceProvider` if you use `@search` -If you use the `@search` directive in your schema, -you will now need to register the service provider `Nuwave\Lighthouse\Scout\ScoutServiceProvider`, -it is no longer registered by default. +If you use the `@search` directive in your schema, you will now need to register the service provider `Nuwave\Lighthouse\Scout\ScoutServiceProvider`, it is no longer registered by default. See [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ### Update `lighthouse.guard` configuration @@ -373,8 +365,7 @@ The `lighthouse.guard` configuration key was renamed to `lighthouse.guards` and + 'guards' => ['api'], ``` -If `lighthouse.guards` configuration is missing, -the default Laravel authentication guard will be used (`auth.defaults.guard`). +If `lighthouse.guards` configuration is missing, the default Laravel authentication guard will be used (`auth.defaults.guard`). ### Update `@auth` and `@whereAuth` directives @@ -399,19 +390,18 @@ The following versions are now the minimal required versions: ### Final schema may change -Parts of the final schema are automatically generated by Lighthouse. Clients that depend on -specific fields or type names may have to adapt. The recommended process for finding breaking -changes is: +Parts of the final schema are automatically generated by Lighthouse. +Clients that depend on specific fields or type names may have to adapt. +The recommended process for finding breaking changes is: 1. Print your schema before upgrading: `php artisan lighthouse:print-schema > old.graphql` 1. Upgrade, then re-print your schema: `php artisan lighthouse:print-schema > new.graphql` 1. Use [graphql-inspector](https://github.com/kamilkisiela/graphql-inspector) to compare your - changes: `graphql-inspector diff old.graphql new.graphql` +changes: `graphql-inspector diff old.graphql new.graphql` ### Rename `resolve` to `__invoke` -Field resolver classes now only support the method name `__invoke`, using -the name `resolve` no longer works. +Field resolver classes now only support the method name `__invoke`, using the name `resolve` no longer works. ```diff namespace App\GraphQL\Queries; @@ -425,7 +415,7 @@ class SomeField ### Replace `@middleware` with `@guard` and specialized FieldMiddleware The `@middleware` directive has been removed, as it violates the boundary between HTTP and GraphQL request handling. -Laravel middleware acts upon the HTTP request as a whole, whereas field middleware must only apply to a part of it. +Laravel middleware acts upon the HTTP request as a whole, whereas field middleware must only apply to a part of it. If you used `@middleware` for authentication, replace it with [@guard](docs/master/api-reference/directives.md#guard): @@ -437,19 +427,17 @@ type Query { ``` Note that [@guard](docs/master/api-reference/directives.md#guard) does not log in users. -To ensure the user is logged in, add the `AttemptAuthenticate` middleware to your `lighthouse.php` -middleware config, see the [default config](src/lighthouse.php) for an example. +To ensure the user is logged in, add the `AttemptAuthenticate` middleware to your `lighthouse.php` middleware config, see the [default config](src/lighthouse.php) for an example. If you used `@middleware` for authorization, replace it with [@can](docs/master/api-reference/directives.md#can). -Other functionality can be replaced by a custom [`FieldMiddleware`](docs/master/custom-directives/field-directives.md#fieldmiddleware) -directive. Just like Laravel Middleware, it can wrap around individual field resolvers. +Other functionality can be replaced by a custom [`FieldMiddleware`](docs/master/custom-directives/field-directives.md#fieldmiddleware) directive. +Just like Laravel Middleware, it can wrap around individual field resolvers. ### Directives must have an SDL definition -The interface `Nuwave\Lighthouse\Support\Contracts\Directive` now has the same functionality -as the removed `Nuwave\Lighthouse\Support\Contracts\DefinedDirective`. If you previously -implemented `DefinedDirective`, remove it from your directives: +The interface `Nuwave\Lighthouse\Support\Contracts\Directive` now has the same functionality as the removed `Nuwave\Lighthouse\Support\Contracts\DefinedDirective`. +If you previously implemented `DefinedDirective`, remove it from your directives: ```diff -use Nuwave\Lighthouse\Support\Contracts\DefinedDirective; @@ -458,8 +446,7 @@ implemented `DefinedDirective`, remove it from your directives: +class TrimDirective extends BaseDirective implements ArgTransformerDirective ``` -Instead of just providing the name of the directive, all directives must now return an SDL -definition that formally describes them. +Instead of just providing the name of the directive, all directives must now return an SDL definition that formally describes them. ```diff - public function name() @@ -490,8 +477,7 @@ definition that formally describes them. ### `@orderBy` argument renamed to `column` -The argument to specify the column to order by when using `@orderBy` was renamed -to `column` to match the `@whereConditions` directive. +The argument to specify the column to order by when using `@orderBy` was renamed to `column` to match the `@whereConditions` directive. Client queries will have to be changed like this: @@ -511,14 +497,12 @@ Client queries will have to be changed like this: } ``` -If you absolutely cannot break your clients, you can re-implement `@orderBy` in your -project - it is a relatively simple `ArgManipulator` directive. +If you absolutely cannot break your clients, you can re-implement `@orderBy` in your project. It is a relatively simple `ArgManipulator` directive. ### `@modelClass` and `@model` changed -The `@model` directive was repurposed to take the place of `@modelClass`. As a replacement -for the current functionality of `@model`, the new `@node` directive was added, -see https://github.com/nuwave/lighthouse/pull/974 for details. +The `@model` directive was repurposed to take the place of `@modelClass`. +As a replacement for the current functionality of `@model`, the new `@node` directive was added, see https://github.com/nuwave/lighthouse/pull/974 for details. You can adapt to this change in two refactoring steps that must be done in order: @@ -542,8 +526,8 @@ You can adapt to this change in two refactoring steps that must be done in order ### Replace `@bcrypt` with `@hash` -The new `@hash` directive is also used for password hashing, but respects the -configuration settings of your Laravel project. +The new `@hash` directive is also used for password hashing. +But respects the configuration settings of your Laravel project. ```diff type Mutation { @@ -557,9 +541,8 @@ type Mutation { ### `@method` passes down just ordered arguments -Instead of passing down the usual resolver arguments, the `@method` directive will -now pass just the arguments given to a field. This behavior could previously be -enabled through the `passOrdered` option, which is now removed. +Instead of passing down the usual resolver arguments, the `@method` directive will now pass just the arguments given to a field. +This behavior could previously be enabled through the `passOrdered` option, which is now removed. ```graphql type User { @@ -582,8 +565,8 @@ This affects custom directives that implemented one of the following interfaces: - `Nuwave\Lighthouse\Support\Contracts\ArgTransformerDirective` - `Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective` -Whereas those interfaces previously extended `Nuwave\Lighthouse\Support\Contracts\ArgDirective`, you now -have to choose if you want them to apply to entire lists of arguments, elements within that list, or both. +Whereas those interfaces previously extended `Nuwave\Lighthouse\Support\Contracts\ArgDirective`, you now have to choose if you want them to apply to entire lists of arguments, elements within that list. +Or both. Change them as follows to make them behave like in v4: ```diff @@ -597,20 +580,18 @@ use Nuwave\Lighthouse\Support\Contracts\DefinedDirective; ### `ArgDirective` run in distinct phases -The application of directives that implement the `ArgDirective` interface is -split into three distinct phases: +The application of directives that implement the `ArgDirective` interface is split into three distinct phases: - Sanitize: Clean the input, e.g. trim whitespace. - Directives can hook into this phase by implementing `ArgSanitizerDirective`. +Directives can hook into this phase by implementing `ArgSanitizerDirective`. - Validate: Ensure the input conforms to the expectations, e.g. check a valid email is given - Transform: Change the input before processing it further, e.g. hashing passwords. - Directives can hook into this phase by implementing `ArgTransformerDirective` +Directives can hook into this phase by implementing `ArgTransformerDirective` ### Replace custom validation directives with validator classes The `ValidationDirective` abstract class was removed in favour of validator classes. -They represent a more lightweight way and flexible way to reuse complex validation rules, -not only on fields but also on input objects. +They represent a more lightweight way and flexible way to reuse complex validation rules, not only on fields but also on input objects. To convert an existing custom validation directive to a validator class, change it as follows: @@ -652,18 +633,16 @@ type Mutation { ### `Nuwave\Lighthouse\Subscriptions\Events\BroadcastSubscriptionEvent` is no longer fired -The event is no longer fired, and the event class was removed. Lighthouse now uses a queued job instead. +The event is no longer fired, and the event class was removed. +Lighthouse now uses a queued job instead. -If you manually fired the event, replace it by queuing a `Nuwave\Lighthouse\Subscriptions\BroadcastSubscriptionJob` -or a call to `Nuwave\Lighthouse\Subscriptions\Contracts\BroadcastsSubscriptions::queueBroadcast()`. +If you manually fired the event, replace it by queuing a `Nuwave\Lighthouse\Subscriptions\BroadcastSubscriptionJob` or a call to `Nuwave\Lighthouse\Subscriptions\Contracts\BroadcastsSubscriptions::queueBroadcast()`. -In case you depend on an event being fired whenever a subscription is queued, you can bind your -own implementation of `Nuwave\Lighthouse\Subscriptions\Contracts\BroadcastsSubscriptions`. +In case you depend on an event being fired whenever a subscription is queued, you can bind your own implementation of `Nuwave\Lighthouse\Subscriptions\Contracts\BroadcastsSubscriptions`. ### `TypeRegistry` does not register duplicates by default -Calling `register()` on the `Nuwave\Lighthouse\Schema\TypeRegistry` now throws when passing -a type that was already registered, as this most likely is an error. +Calling `register()` on the `Nuwave\Lighthouse\Schema\TypeRegistry` now throws when passing a type that was already registered, as this most likely is an error. If you want to previous behavior of overwriting existing types, use `overwrite()` instead. @@ -688,8 +667,7 @@ If you need to revert to the old behavior of using `fill()`, you can change your ### Replace `ErrorBuffer` with `ErrorPool` -Collecting partial errors is now done through the singleton `Nuwave\Lighthouse\Execution\ErrorPool` -instead of `Nuwave\Lighthouse\Execution\ErrorBuffer`: +Collecting partial errors is now done through the singleton `Nuwave\Lighthouse\Execution\ErrorPool` instead of `Nuwave\Lighthouse\Execution\ErrorBuffer`: ```php try { @@ -704,8 +682,7 @@ return $result; ### Use native `TestResponse::json()` -The `TestResponse::jsonGet()` mixin was removed in favor of the `->json()` method, -natively supported by Laravel starting from version 5.6. +The `TestResponse::jsonGet()` mixin was removed in favor of the `->json()` method, natively supported by Laravel starting from version 5.6. ```diff $response = $this->graphQL(...); @@ -742,8 +719,7 @@ A few are different: ### Add method `defaultHasOperator` to `Nuwave\Lighthouse\WhereConditions\Operator` -Since the addition of the `HAS` input in `whereCondition` mechanics, -there has to be a default operator for the `HAS` input. +Since the addition of the `HAS` input in `whereCondition` mechanics, there has to be a default operator for the `HAS` input. If you implement your own custom operator, implement `defaultHasOperator`. For example, this is the implementation of the default `Nuwave\Lighthouse\WhereConditions\SQLOperator`: @@ -776,15 +752,14 @@ You can now discard errors by returning `null` from the handler. ### Upgrade to `mll-lab/graphql-php-scalars` v4 -If you use complex where condition directives, such as `@whereConditions`, -upgrade `mll-lab/graphql-php-scalars` to v4: +If you use complex where condition directives, such as `@whereConditions`, upgrade `mll-lab/graphql-php-scalars` to v4: composer require mll-lab/graphql-php-scalars:^4 ### Subscriptions version 1 removal -Subscriptions only use version 2 now. That means, the extensions content -will not contain the `channels` and `version` key anymore. +Subscriptions only use version 2 now. +That means, the extensions content will not contain the `channels` and `version` key anymore. ```diff { diff --git a/docs/.github/README.md b/docs/.github/README.md index 4d9cf32e7f..ca34c2ee98 100644 --- a/docs/.github/README.md +++ b/docs/.github/README.md @@ -1,7 +1,6 @@ # Lighthouse Website -The Lighthouse docs website uses [Vue Press](https://vuepress.vuejs.org), -a minimalistic [Vue](https://vuejs.org) powered static site generator. +The Lighthouse docs website uses [Vue Press](https://vuepress.vuejs.org), a minimalistic [Vue](https://vuejs.org) powered static site generator. ## Directory structure @@ -73,10 +72,17 @@ Always use relative paths according to folder structure. See [configuration](../getting-started/configuration.md) for more info. ``` +### Prose formatting + +Use [Semantic Line Breaks](https://sembr.org) in docs prose. +Use one sentence per line by default. +Do not split a sentence at commas or clauses. +If a sentence is too long, rewrite it into multiple shorter sentences. +Do not reflow code blocks, tables, or other syntax-sensitive structures. + ## Versioning -The numbered directories (2, 3, ...) in `docs/` correspond to major releases of Lighthouse, -`docs/pages/` remains the same for all versions. +The numbered directories (2, 3, ...) in `docs/` correspond to major releases of Lighthouse, `docs/pages/` remains the same for all versions. This ensures that the docs are always in sync with the released version of Lighthouse. Version specific changes are handled by keeping the docs for each version separate. @@ -94,15 +100,13 @@ See [Tagging a new version](#tagging-a-new-version) for how they are released. ### Updating existing versions -When you improve the docs, consider if the change you are making applies to -multiple versions of Lighthouse. +When you improve the docs, consider if the change you are making applies to multiple versions of Lighthouse. Change the relevant parts of each docs folder and commit it all in a single PR. ### Tagging a new version -After you finished your work on `docs/master/`, copy the updated docs -into the directory of the current major version by running: +After you finished your work on `docs/master/`, copy the updated docs into the directory of the current major version by running: make release @@ -114,4 +118,3 @@ The docs are automatically built and deployed on pushes to `master`. @chrissm79 set up the deployment. When the docs are down, check https://www.netlifystatus.com for problems on their part. - diff --git a/docs/2/api-reference/directives.md b/docs/2/api-reference/directives.md index 03c56ac304..d378d01e9a 100644 --- a/docs/2/api-reference/directives.md +++ b/docs/2/api-reference/directives.md @@ -20,8 +20,8 @@ type Query { } ``` -This assumes your model has the same name as the type you are returning and is defined -in the default model namespace `App\Models`. [You can change this configuration](../getting-started/configuration.md). +This assumes your model has the same name as the type you are returning and is defined in the default model namespace `App\Models`. +[You can change this configuration](../getting-started/configuration.md). If you need to use a different model for a single field, you can pass a class name as the `model` argument. @@ -60,8 +60,7 @@ class Post extends Model } ``` -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type Post { @@ -98,8 +97,7 @@ class User extends Model } ``` -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type User { @@ -150,8 +148,7 @@ type Query { } ``` -You can set an expiration time in seconds -if you want to invalidate the cache after a while. +You can set an expiration time in seconds if you want to invalidate the cache after a while. ```graphql type Query { @@ -170,7 +167,9 @@ type Query { ## @cacheKey -When generating a cached result for a resolver, Lighthouse produces a unique key for each type. By default, Lighthouse will look for a field with the `ID` type to generate the key. If you'd like to use a different field (i.e., an external API id) you can mark the field with the `@cacheKey` directive. +When generating a cached result for a resolver, Lighthouse produces a unique key for each type. +By default, Lighthouse will look for a field with the `ID` type to generate the key. +If you'd like to use a different field (i.e., an external API id) you can mark the field with the `@cacheKey` directive. ```graphql type GithubProfile { @@ -205,7 +204,8 @@ class PostPolicy ## @complexity -Place on fields to perform analysis to calculate a query complexity score before execution. [Read More](https://webonyx.github.io/graphql-php/security/#query-complexity-analysis) +Place on fields to perform analysis to calculate a query complexity score before execution. +[Read More](https://webonyx.github.io/graphql-php/security/#query-complexity-analysis) ```graphql type Query { @@ -252,7 +252,8 @@ type Mutation { ## @delete -Delete a model with a given id field. The field must be an `ID` type. +Delete a model with a given id field. +The field must be an `ID` type. ```graphql type Mutation { @@ -270,8 +271,7 @@ type Mutation { ``` You can also delete multiple models at once. -Define a field that takes a list of IDs and returns a Collection of the -deleted models. +Define a field that takes a list of IDs and returns a Collection of the deleted models. ```graphql type Mutation { @@ -283,9 +283,8 @@ type Mutation { Specify a custom resolver function for a single field. -In most cases, you do not even need this directive. Make sure you read about -the built in directives for [querying data](../the-basics/fields.md#query-data) and [mutating data](../the-basics/fields.md#mutate-data), -as well as the convention based approach to [implementing custom resolvers](../the-basics/fields.md#custom-resolvers). +In most cases, you do not even need this directive. +Make sure you read about the built in directives for [querying data](../the-basics/fields.md#query-data) and [mutating data](../the-basics/fields.md#mutate-data), as well as the convention based approach to [implementing custom resolvers](../the-basics/fields.md#custom-resolvers). Pass a class and a method to the `resolver` argument and separate them with an `@` symbol. @@ -296,9 +295,8 @@ type Mutation { } ``` -If your field is defined on the root types `Query` or `Mutation`, you can take advantage -of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). The following -will look for a class in `App\Http\GraphQL\Queries` by default. +If your field is defined on the root types `Query` or `Mutation`, you can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). +The following will look for a class in `App\Http\GraphQL\Queries` by default. ```graphql type Query { @@ -306,8 +304,8 @@ type Query { } ``` -Be aware that resolvers are not limited to root fields. A resolver can be used for basic tasks -such as transforming the value of scalar fields, e.g. reformat a date. +Be aware that resolvers are not limited to root fields. +A resolver can be used for basic tasks such as transforming the value of scalar fields, e.g. reformat a date. ```graphql type User { @@ -343,8 +341,8 @@ Other than [@find](#find), this will not throw an error if more than one items a ## @enum -Map the underlying value to an enum key. When dealing with the Enum type in your code, -you will receive the defined value instead of the string key. +Map the underlying value to an enum key. +When dealing with the Enum type in your code, you will receive the defined value instead of the string key. ```graphql enum Role { @@ -364,8 +362,7 @@ type User { } ``` -If the name of the argument does not match the database column, -pass the actual column name as the `key`. +If the name of the argument does not match the database column, pass the actual column name as the `key`. ```graphql type User { @@ -375,7 +372,8 @@ type User { ## @event -Fire an event after a mutation has taken place. It requires the `fire` argument that should be the class name of the event you want to fire. +Fire an event after a mutation has taken place. +It requires the `fire` argument that should be the class name of the event you want to fire. ```graphql type Mutation { @@ -395,15 +393,13 @@ type User { } ``` -Instead of the original ID, the `id` field will now return a base64-encoded String that globally identifies the User and can be used -for querying the `node` endpoint. +Instead of the original ID, the `id` field will now return a base64-encoded String that globally identifies the User and can be used for querying the `node` endpoint. ## @group Apply common settings to all fields of an Object Type. -Set a common namespace for the [@field](#field) and the [@complexity](#complexity) directives -that are defined on the fields of the defined type. +Set a common namespace for the [@field](#field) and the [@complexity](#complexity) directives that are defined on the fields of the defined type. ```graphql extend type Query @group(namespace: "App\\Models") { @@ -438,8 +434,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -457,8 +452,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -479,7 +473,8 @@ type Query { ## @inject -Inject a value from the context object into the arguments. This is really useful with the `@create` directive that rely on the authenticated user's `id` that you don't want the client to fill in themselves. +Inject a value from the context object into the arguments. +This is really useful with the `@create` directive that rely on the authenticated user's `id` that you don't want the client to fill in themselves. ```graphql type Mutation { @@ -491,8 +486,7 @@ type Mutation { ## @interface -Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding -to use this directive, you probably don't need it. +Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding to use this directive, you probably don't need it. You can point Lighthouse to a custom type resolver. Set the `resolver` argument to a function that returns the implementing Object Type. @@ -504,8 +498,8 @@ interface Commentable } ``` -The function receives the value of the parent field as its single argument and must -return an Object Type. You can get the appropriate Object Type from Lighthouse's type registry. +The function receives the value of the parent field as its single argument and must return an Object Type. +You can get the appropriate Object Type from Lighthouse's type registry. ```php myData`) -but rather via a method like `$model->myData()`. It requires the `name` argument. +This comes in handy if the data is not accessible as an attribute (e.g. `$model->myData`) but rather via a method like `$model->myData()`. +It requires the `name` argument. ```graphql type User { @@ -560,8 +554,8 @@ type User { ## @middleware -Run Laravel middleware for a specific field. This can be handy to reuse existing -middleware. +Run Laravel middleware for a specific field. +This can be handy to reuse existing middleware. ```graphql type Query { @@ -569,8 +563,8 @@ type Query { } ``` -You can define middleware just like you would in Laravel. Pass in either a fully qualified -class name, an alias or a middleware group - or any combination of them. +You can define middleware just like you would in Laravel. +Pass in either a fully qualified class name, an alias or a middleware group - or any combination of them. ```graphql type Query { @@ -596,9 +590,8 @@ extend type Query { } ``` -Other than global middleware defined in the [configuration](../getting-started/configuration.md), field middleware -only applies to the specific field it is defined on. This has the benefit of limiting errors -to particular fields and not failing an entire request if a middleware fails. +Other than global middleware defined in the [configuration](../getting-started/configuration.md), field middleware only applies to the specific field it is defined on. +This has the benefit of limiting errors to particular fields and not failing an entire request if a middleware fails. There are a few caveats to field middleware though: @@ -608,8 +601,7 @@ There are a few caveats to field middleware though: but rather the slice of data that the particular field returned. - The `terminate` method of field middleware is not called. -If the middleware needs to be aware of GraphQL specifics, such as the resolver arguments, -it is often more suitable to define a custom field directive. +If the middleware needs to be aware of GraphQL specifics, such as the resolver arguments, it is often more suitable to define a custom field directive. ## @model @@ -636,8 +628,7 @@ type User { ## @node Store a type's resolver functions in Lighthouse's node registry. -The `resolver` argument has to specify a function which will be passed the -decoded `id` and resolves to a result. +The `resolver` argument has to specify a function which will be passed the decoded `id` and resolves to a result. ```graphql type User @node(resolver: "App\\GraphQL\\NodeResolver@resolveUser") { @@ -649,9 +640,8 @@ type User @node(resolver: "App\\GraphQL\\NodeResolver@resolveUser") { public function resolveUser(string $id): \App\User ``` -The `typeResolver` is responsible for determining the GraphQL type the result -belongs to. Lighthouse provides a default implementation, but you can override -it if the need arises. +The `typeResolver` is responsible for determining the GraphQL type the result belongs to. +Lighthouse provides a default implementation, but you can override it if the need arises. ```graphql type User @@ -680,8 +670,8 @@ type Query { ## @paginate -Return a paginated list. This transforms the schema definition and automatically adds -additional arguments and inbetween types. +Return a paginated list. +This transforms the schema definition and automatically adds additional arguments and inbetween types. ```graphql type Query { @@ -689,8 +679,7 @@ type Query { } ``` -The `type` of pagination defaults to `paginator`, but may also be set to a Relay -compliant `connection`. +The `type` of pagination defaults to `paginator`, but may also be set to a Relay compliant `connection`. ```graphql type Query { @@ -698,8 +687,8 @@ type Query { } ``` -By default, this looks for an Eloquent model in the configured default namespace, with the same -name as the returned type. You can overwrite this by setting the `model` argument. +By default, this looks for an Eloquent model in the configured default namespace, with the same name as the returned type. +You can overwrite this by setting the `model` argument. ```graphql type Query { @@ -798,8 +787,7 @@ scalar DateTime Creates a full-text search argument. -This directive will make an argument use [Laravel Scout](https://laravel.com/docs/scout) -to make a full-text search, what driver you use for Scout is up to you. +This directive will make an argument use [Laravel Scout](https://laravel.com/docs/scout) to make a full-text search, what driver you use for Scout is up to you. The `search` method of the model is called with the value of the argument. @@ -838,8 +826,7 @@ type Mutation { ## @union -Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding -to use this directive, you probably don't need it. +Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding to use this directive, you probably don't need it. You can point Lighthouse to a custom type resolver. Set the `resolver` argument to a function that returns the implementing Object Type. @@ -858,8 +845,8 @@ union Person @union(resolver: "App\\GraphQL\\UnionResolver@person") = | Employee ``` -The function receives the value of the parent field as its single argument and must -return an Object Type. You can get the appropriate Object Type from Lighthouse's type registry. +The function receives the value of the parent field as its single argument and must return an Object Type. +You can get the appropriate Object Type from Lighthouse's type registry. ```php ` -and including it in your schema. Lighthouse will look for Scalar types in a configurable -default namespace. +Define your own scalar types by running `php artisan lighthouse:scalar ` and including it in your schema. +Lighthouse will look for Scalar types in a configurable default namespace. ```graphql scalar ZipCode @@ -57,8 +55,8 @@ scalar Email @scalar(class: "MLL\\GraphQLScalars\\Email") ## Enum Enums are types with a restricted set of values (similar to `enum` found in database migrations). -They are defined as a list of `UPPERCASE` string keys. You can define the actual values through -the [@enum](../api-reference/directives.md#enum) directive. +They are defined as a list of `UPPERCASE` string keys. +You can define the actual values through the [@enum](../api-reference/directives.md#enum) directive. ```graphql enum EmploymentStatus { @@ -82,8 +80,8 @@ type Query { } ``` -In this example, the underlying values are actually integers. When the models are retrieved from -the database, the mapping is applied and the integers are converted to the defined string keys. +In this example, the underlying values are actually integers. +When the models are retrieved from the database, the mapping is applied and the integers are converted to the defined string keys. ```php return [ @@ -129,8 +127,7 @@ The PHP internal value of the field `ADMIN` will be `string('ADMIN')`. ## Input Input types can be used to describe complex objects for field arguments. -Beware that while they look similar to Object Types, they behave differently: -The fields of an Input Type are treated similar to arguments. +Beware that while they look similar to Object Types, they behave differently: The fields of an Input Type are treated similar to arguments. ```graphql input CreateUserInput { @@ -178,21 +175,19 @@ type User implements Named { } ``` -Interfaces need a way of determining which concrete Object Type is returned by a -particular query. Lighthouse provides a default type resolver that works by calling -`class_basename($value)` on the value returned by the resolver. +Interfaces need a way of determining which concrete Object Type is returned by a particular query. +Lighthouse provides a default type resolver that works by calling `class_basename($value)` on the value returned by the resolver. -You can also provide a custom type resolver. Run `php artisan lighthouse:interface ` to create -a custom interface class. It is automatically put in the default namespace where Lighthouse can discover it by itself. +You can also provide a custom type resolver. +Run `php artisan lighthouse:interface ` to create a custom interface class. +It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) ## Union A Union is an abstract type that simply enumerates other Object Types. -They are similar to interfaces in that they can return different types, but they can not -have fields defined. +They are similar to interfaces in that they can return different types, but they can not have fields defined. ```graphql union Person = User | Employee @@ -206,10 +201,8 @@ type Employee { } ``` -Just like Interfaces, you need a way to determine the concrete Object Type for a Union, -based on the resolved value. If the default type resolver does not work for you, define your -own using `php artisan lighthouse:union `. +Just like Interfaces, you need a way to determine the concrete Object Type for a Union, based on the resolved value. +If the default type resolver does not work for you, define your own using `php artisan lighthouse:union `. It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) diff --git a/docs/3/api-reference/commands.md b/docs/3/api-reference/commands.md index 0e60ee8995..3993e6e78d 100644 --- a/docs/3/api-reference/commands.md +++ b/docs/3/api-reference/commands.md @@ -1,7 +1,7 @@ # Artisan Commands -Lighthouse provides some convenient artisan commands. All of them -are namespaced under `lighthouse`. +Lighthouse provides some convenient artisan commands. +All of them are namespaced under `lighthouse`. ## clear-cache @@ -27,12 +27,10 @@ Compile the final GraphQL schema and print the result. php artisan lighthouse:print-schema -This can be quite useful, as the root `.graphql` files do not necessarily -contains the whole schema. Schema imports, native PHP types and schema manipulation -may influence the final schema. +This can be quite useful, as the root `.graphql` files do not necessarily contains the whole schema. +Schema imports, native PHP types and schema manipulation may influence the final schema. -Use the `-W` / `--write` option to output the schema to the default file storage -(usually `storage/app`) as `lighthouse-schema.graphql`. +Use the `-W` / `--write` option to output the schema to the default file storage (usually `storage/app`) as `lighthouse-schema.graphql`. ## query diff --git a/docs/3/api-reference/directives.md b/docs/3/api-reference/directives.md index 9178eb851d..5bde85af7d 100644 --- a/docs/3/api-reference/directives.md +++ b/docs/3/api-reference/directives.md @@ -10,8 +10,8 @@ type Query { } ``` -This assumes your model has the same name as the type you are returning and is defined -in the default model namespace `App`. [You can change this configuration](../getting-started/configuration.md). +This assumes your model has the same name as the type you are returning and is defined in the default model namespace `App`. +[You can change this configuration](../getting-started/configuration.md). ### Definition @@ -66,8 +66,7 @@ directive @auth( ### Examples -If you need to use a guard besides the default to resolve the authenticated user, -you can pass the guard name as the `guard` argument +If you need to use a guard besides the default to resolve the authenticated user, you can pass the guard name as the `guard` argument ```graphql type Query { @@ -123,8 +122,7 @@ directive @belongsTo( ### Examples -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type Post { @@ -193,8 +191,7 @@ directive @belongsToMany( ### Examples -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type User { @@ -251,8 +248,7 @@ directive @broadcast( ### Examples -You may override the default queueing behaviour from the configuration by -passing the `shouldQueue` argument. +You may override the default queueing behaviour from the configuration by passing the `shouldQueue` argument. ```graphql type Mutation { @@ -273,8 +269,7 @@ type Query { } ``` -You must point to a `method` which will receive the builder instance -and the argument value and can apply additional constraints to the query. +You must point to a `method` which will receive the builder instance and the argument value and can apply additional constraints to the query. ```php namespace App; @@ -342,8 +337,7 @@ directive @cache( ### Examples -You can set an expiration time in seconds -if you want to invalidate the cache after a while. +You can set an expiration time in seconds if you want to invalidate the cache after a while. ```graphql type Query { @@ -362,7 +356,9 @@ type Query { ## @cacheKey -When generating a cached result for a resolver, Lighthouse produces a unique key for each type. By default, Lighthouse will look for a field with the `ID` type to generate the key. If you'd like to use a different field (i.e., an external API id) you can mark the field with the `@cacheKey` directive. +When generating a cached result for a resolver, Lighthouse produces a unique key for each type. +By default, Lighthouse will look for a field with the `ID` type to generate the key. +If you'd like to use a different field (i.e., an external API id) you can mark the field with the `@cacheKey` directive. ```graphql type GithubProfile { @@ -435,8 +431,7 @@ class PostPolicy } ``` -The name of the returned Type `Post` is used as the Model class, however you may overwrite this by -passing the `model` argument. +The name of the returned Type `Post` is used as the Model class, however you may overwrite this by passing the `model` argument. ```graphql type Mutation { @@ -495,8 +490,7 @@ type Query { } ``` -A custom complexity function may look like the following, -refer to the [complexity function signature](resolvers.md#complexity-function-signature). +A custom complexity function may look like the following, refer to the [complexity function signature](resolvers.md#complexity-function-signature). ```php namespace App\Security; @@ -537,8 +531,7 @@ directive @create( ### Examples -If you are using a single input object as an argument, you must tell Lighthouse -to spread out the nested values before applying it to the resolver. +If you are using a single input object as an argument, you must tell Lighthouse to spread out the nested values before applying it to the resolver. _Note_: The usage of `flatten` is deprecated. @@ -552,8 +545,7 @@ input CreatePostInput { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, or is located in a non-default namespace, set it with the `model` argument. ```graphql type Mutation { @@ -599,8 +591,7 @@ type Mutation { ``` You can also delete multiple models at once. -Define a field that takes a list of IDs and returns a Collection of the -deleted models. +Define a field that takes a list of IDs and returns a Collection of the deleted models. ```graphql type Mutation { @@ -608,8 +599,7 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, or is located in a non-default namespace, set it with the `model` argument. ```graphql type Mutation { @@ -619,9 +609,8 @@ type Mutation { ## @deprecated -You can mark fields as deprecated by adding the `@deprecated` directive and providing a -`reason`. Deprecated fields are not included in introspection queries unless -requested and they can still be queried by clients. +You can mark fields as deprecated by adding the `@deprecated` directive and providing a `reason`. +Deprecated fields are not included in introspection queries unless requested and they can still be queried by clients. ```graphql type Query { @@ -650,9 +639,8 @@ directive @deprecated( Assign a resolver function to a field. -In most cases, you do not even need this directive. Make sure you read about -the built in directives for [querying data](../the-basics/fields.md#query-data) and [mutating data](../the-basics/fields.md#mutate-data), -as well as the convention based approach to [implementing custom resolvers](../the-basics/fields.md#custom-resolvers). +In most cases, you do not even need this directive. +Make sure you read about the built in directives for [querying data](../the-basics/fields.md#query-data) and [mutating data](../the-basics/fields.md#mutate-data), as well as the convention based approach to [implementing custom resolvers](../the-basics/fields.md#custom-resolvers). Pass a class and a method to the `resolver` argument and separate them with an `@` symbol. @@ -685,9 +673,8 @@ directive @field( ### Examples -If your field is defined on the root types `Query` or `Mutation`, you can take advantage -of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). The following -will look for a class in `App\GraphQL\Queries` by default. +If your field is defined on the root types `Query` or `Mutation`, you can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). +The following will look for a class in `App\GraphQL\Queries` by default. ```graphql type Query { @@ -695,8 +682,8 @@ type Query { } ``` -Be aware that resolvers are not limited to root fields. A resolver can be used for basic tasks -such as transforming the value of scalar fields, e.g. reformat a date. +Be aware that resolvers are not limited to root fields. +A resolver can be used for basic tasks such as transforming the value of scalar fields, e.g. reformat a date. ```graphql type User { @@ -809,8 +796,8 @@ enum Role { } ``` -You do not need this directive if the internal value of each enum key -is an identical string. [Read more about enum types](../the-basics/types.md#enum) +You do not need this directive if the internal value of each enum key is an identical string. +[Read more about enum types](../the-basics/types.md#enum) ## @eq @@ -836,8 +823,7 @@ directive @eq( ### Examples -If the name of the argument does not match the database column, -pass the actual column name as the `key`. +If the name of the argument does not match the database column, pass the actual column name as the `key`. ```graphql type User { @@ -848,8 +834,7 @@ type User { ## @event Fire an event after a mutation has taken place. -It requires the `dispatch` argument that should be -the class name of the event you want to fire. +It requires the `dispatch` argument that should be the class name of the event you want to fire. ```graphql type Mutation { @@ -880,8 +865,7 @@ type User { } ``` -Instead of the original ID, the `id` field will now return a base64-encoded String -that globally identifies the User and can be used for querying the `node` endpoint. +Instead of the original ID, the `id` field will now return a base64-encoded String that globally identifies the User and can be used for querying the `node` endpoint. ### Definition @@ -909,18 +893,15 @@ type Mutation { } ``` -The field resolver will receive the decoded version of the passed `id`, -split into type and ID. +The field resolver will receive the decoded version of the passed `id`, split into type and ID. -You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global ids. +You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global ids. ## @group Apply common settings to all fields of an Object Type. -Set a common namespace for the [@field](#field) and the [@complexity](#complexity) directives -that are defined on the fields of the defined type. +Set a common namespace for the [@field](#field) and the [@complexity](#complexity) directives that are defined on the fields of the defined type. ```graphql extend type Query @group(namespace: "App\\Authentication") { @@ -1002,8 +983,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -1043,8 +1023,7 @@ directive @hasOne( ### Examples -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -1086,8 +1065,7 @@ type Mutation { } ``` -This is useful to ensure that the authenticated user's `id` is -automatically used for creating new models and can not be manipulated. +This is useful to ensure that the authenticated user's `id` is automatically used for creating new models and can not be manipulated. ### Definition @@ -1111,8 +1089,7 @@ directive @inject( ### Examples -If you are using an Input Object as an argument, you can use dot notation to -set a nested argument. +If you are using an Input Object as an argument, you can use dot notation to set a nested argument. ```graphql type Mutation { @@ -1126,8 +1103,7 @@ type Mutation { Use a custom resolver to determine the concrete type of an interface. -Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding -to use this directive, you probably don't need it. +Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding to use this directive, you probably don't need it. Set the `resolver` argument to a function that returns the implementing Object Type. @@ -1138,8 +1114,8 @@ interface Commentable } ``` -The function receives the value of the parent field as its single argument and must -return an Object Type. You can get the appropriate Object Type from Lighthouse's type registry. +The function receives the value of the parent field as its single argument and must return an Object Type. +You can get the appropriate Object Type from Lighthouse's type registry. ```php -![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) -_(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ +![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) _(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ diff --git a/docs/3/performance/n-plus-one.md b/docs/3/performance/n-plus-one.md index 91510dcaf9..df4d40dd63 100644 --- a/docs/3/performance/n-plus-one.md +++ b/docs/3/performance/n-plus-one.md @@ -1,10 +1,8 @@ # The N+1 Query Problem -A common performance pitfall that comes with the nested nature of GraphQL queries -is the so-called N+1 query problem. +A common performance pitfall that comes with the nested nature of GraphQL queries is the so-called N+1 query problem. -Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the -name of the associated author: +Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the name of the associated author: ```graphql { @@ -17,18 +15,14 @@ name of the associated author: } ``` -Following a naive execution strategy, Lighthouse would first query a list of posts, -then loop over that list and resolve the individual fields. -The associated author for each post would be lazily loaded, querying the database -once per post. +Following a naive execution strategy, Lighthouse would first query a list of posts, then loop over that list and resolve the individual fields. +The associated author for each post would be lazily loaded, querying the database once per post. ## Eager Loading Relationships -When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) -is commonly used to alleviate the N+1 query problem. +When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) is commonly used to alleviate the N+1 query problem. -You can leverage eager loading by informing Lighthouse of the relationships between your models, -using directives such as [`@belongsTo`](../api-reference/directives.md#belongsto) and [`@hasMany`](../api-reference/directives.md#hasmany). +You can leverage eager loading by informing Lighthouse of the relationships between your models, using directives such as [`@belongsTo`](../api-reference/directives.md#belongsto) and [`@hasMany`](../api-reference/directives.md#hasmany). ```graphql type Post { @@ -44,12 +38,11 @@ type User { Under the hood, Lighthouse will batch the relationship queries together in a single database query. -If you require a relation to be loaded for some field, but do not wish to return the relationship itself, -you can use the [`@with`](../api-reference/directives.md#with) directive. +If you require a relation to be loaded for some field. +Do not wish to return the relationship itself, you can use the [`@with`](../api-reference/directives.md#with) directive. ## Data Loader -`webonyx/graphql-php` allows deferring the actual resolution of a field until it is actually needed, -read more [in their documentation](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). +`webonyx/graphql-php` allows deferring the actual resolution of a field until it is actually needed, read more [in their documentation](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). You can extend `\Nuwave\Lighthouse\Execution\DataLoader\BatchLoader` if you require custom batch loading. diff --git a/docs/3/performance/schema-caching.md b/docs/3/performance/schema-caching.md index 54d3144bfb..f7b06543db 100644 --- a/docs/3/performance/schema-caching.md +++ b/docs/3/performance/schema-caching.md @@ -1,7 +1,6 @@ # Schema caching -As your schema grows larger, the construction of the schema from raw `.graphql` files -becomes more and more costly. +As your schema grows larger, the construction of the schema from raw `.graphql` files becomes more and more costly. Make sure to enable schema caching when shipping Lighthouse to production. diff --git a/docs/3/performance/server-configuration.md b/docs/3/performance/server-configuration.md index 9339ebf235..561c14b335 100644 --- a/docs/3/performance/server-configuration.md +++ b/docs/3/performance/server-configuration.md @@ -9,5 +9,4 @@ If you have the freedom to install it on your server, it's an easy way to get a ## Xdebug -Enabling Xdebug and having an active debug session slows down execution by -an order of magnitude. +Enabling Xdebug and having an active debug session slows down execution by an order of magnitude. diff --git a/docs/3/security/authentication.md b/docs/3/security/authentication.md index b564838d2f..bb4f7c8460 100644 --- a/docs/3/security/authentication.md +++ b/docs/3/security/authentication.md @@ -1,7 +1,7 @@ # Authentication -You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) -to authenticate users of your GraphQL API. Stateless guards are recommended for most use cases. +You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) to authenticate users of your GraphQL API. +Stateless guards are recommended for most use cases. ## Get the current user @@ -14,8 +14,7 @@ type Query { } ``` -Sending the following query will return the authenticated user's info -or `null` if the request is not authenticated. +Sending the following query will return the authenticated user's info or `null` if the request is not authenticated. ```graphql { @@ -28,11 +27,9 @@ or `null` if the request is not authenticated. ## Apply auth middleware -Lighthouse allows you to configure global middleware that is run for every -request to your endpoint, but also define it on a per-field basis. +Lighthouse allows you to configure global middleware that is run for every request to your endpoint, but also define it on a per-field basis. -Use the [@middleware](../api-reference/directives.md#middleware) directive to apply Laravel middleware, -such as the `auth` middleware, to selected fields of your GraphQL endpoint. +Use the [@middleware](../api-reference/directives.md#middleware) directive to apply Laravel middleware, such as the `auth` middleware, to selected fields of your GraphQL endpoint. ```graphql type Query { diff --git a/docs/3/security/resource-exhaustion.md b/docs/3/security/resource-exhaustion.md index 27fdc82848..168d7e8eb2 100644 --- a/docs/3/security/resource-exhaustion.md +++ b/docs/3/security/resource-exhaustion.md @@ -1,10 +1,10 @@ # Preventing Resource Exhaustion -GraphQL gives enormous power to clients. But with great power come great responsibilities đŸ•·. +GraphQL gives enormous power to clients. +But with great power come great responsibilities đŸ•·. -Since clients have the possibility to craft very complex queries, our servers must be ready -to handle them properly. These queries may be abusive queries from evil clients, -or may simply be very large queries used by legitimate clients. +Since clients have the possibility to craft very complex queries, our servers must be ready to handle them properly. +These queries may be abusive queries from evil clients, or may simply be very large queries used by legitimate clients. In both of these cases, the client can potentially take your GraphQL server down. _This intro was taken from HowToGraphQL, we recommend reading their full chapter on security https://www.howtographql.com/advanced/4-security/_ diff --git a/docs/3/security/validation.md b/docs/3/security/validation.md index 746081d035..935a05d515 100644 --- a/docs/3/security/validation.md +++ b/docs/3/security/validation.md @@ -2,9 +2,8 @@ ## Validating Arguments -Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) for your -queries and mutations. The simplest way to leverage the built-in validation rules is to use the -[@rules](../api-reference/directives.md#rules) directive. +Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) for your queries and mutations. +The simplest way to leverage the built-in validation rules is to use the [@rules](../api-reference/directives.md#rules) directive. ```graphql type Mutation { @@ -15,8 +14,7 @@ type Mutation { } ``` -In the case of a validation error, Lighthouse will abort execution and return the validation messages -as part of the response. +In the case of a validation error, Lighthouse will abort execution and return the validation messages as part of the response. ```graphql mutation { @@ -58,11 +56,9 @@ You can customize the error message for a particular argument. ### Validating For Uniqueness -Using the [`unique`](https://laravel.com/docs/5.8/validation#rule-unique) -validation rule can be a bit tricky. +Using the [`unique`](https://laravel.com/docs/5.8/validation#rule-unique) validation rule can be a bit tricky. -If the argument is nested within an input object, the argument path will not -match the column name, so you have to specify the column name explicitly. +If the argument is nested within an input object, the argument path will not match the column name, so you have to specify the column name explicitly. ```graphql input CreateUserInput { @@ -72,8 +68,7 @@ input CreateUserInput { ## Validating Arrays -When you are passing in an array as an argument to a field, you might -want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rules) +When you are passing in an array as an argument to a field, you might want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rules) ```graphql type Mutation { @@ -81,8 +76,7 @@ type Mutation { } ``` -You can also combine this with [@rules](../api-reference/directives.md#rules) to validate -both the size and the contents of an argument array. +You can also combine this with [@rules](../api-reference/directives.md#rules) to validate both the size and the contents of an argument array. For example, you might require a list of at least 3 valid emails to be passed. ```graphql diff --git a/docs/3/subscriptions/client-implementations.md b/docs/3/subscriptions/client-implementations.md index 7393198a42..3ec10307cd 100644 --- a/docs/3/subscriptions/client-implementations.md +++ b/docs/3/subscriptions/client-implementations.md @@ -1,12 +1,10 @@ # Client Implementations -To get you up and running quickly, the following sections show how to use subcriptions -with common GraphQL client libraries. +To get you up and running quickly, the following sections show how to use subcriptions with common GraphQL client libraries. ## Apollo -To use Lighthouse subscriptions with the [Apollo](https://www.apollographql.com/docs/react) -client library you will need to create an `apollo-link` +To use Lighthouse subscriptions with the [Apollo](https://www.apollographql.com/docs/react) client library you will need to create an `apollo-link` ```js import { ApolloLink, Observable } from "apollo-link"; @@ -89,8 +87,7 @@ const link = ApolloLink.from([pusherLink, httpLink(`${API_LOCATION}/graphql`)]); ## Relay Modern -To use Lighthouse's subscriptions with Relay Modern you will -need to create a custom handler and inject it into Relay's environment. +To use Lighthouse's subscriptions with Relay Modern you will need to create a custom handler and inject it into Relay's environment. ```js import Pusher from "pusher-js"; @@ -202,8 +199,7 @@ export const environment = new Environment({ ## Flutter/Dart -To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will -need to create a custom link below: +To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will need to create a custom link below: ````dart import 'dart:async'; diff --git a/docs/3/subscriptions/defining-fields.md b/docs/3/subscriptions/defining-fields.md index 39099ebfcd..e51b863358 100644 --- a/docs/3/subscriptions/defining-fields.md +++ b/docs/3/subscriptions/defining-fields.md @@ -12,13 +12,10 @@ The quickest way to define such a field is through the `artisan` generator comma php artisan lighthouse:subscription PostUpdated -Lighthouse will look for a class with the capitalized name of the field that -is defined within the default subscription namespace. -For example, the field `postUpdated` should have a corresponding class at -`App\GraphQL\Subscriptions\PostUpdated`. +Lighthouse will look for a class with the capitalized name of the field that is defined within the default subscription namespace. +For example, the field `postUpdated` should have a corresponding class at `App\GraphQL\Subscriptions\PostUpdated`. -All subscription field classes **must** implement the abstract class -`Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` and implement two methods: +All subscription field classes **must** implement the abstract class `Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` and implement two methods. `authorize` and `filter`. ```php @@ -119,6 +116,4 @@ class PostUpdated extends GraphQLSubscription } ``` -If the default namespaces are not working with your application structure -or you want to be more explicit, you can use the [`@subscription`](../api-reference/directives.md#subscription) -directive to point to a different class. +If the default namespaces are not working with your application structure or you want to be more explicit, you can use the [`@subscription`](../api-reference/directives.md#subscription) directive to point to a different class. diff --git a/docs/3/subscriptions/filtering-subscriptions.md b/docs/3/subscriptions/filtering-subscriptions.md index b4edc3e84c..9ddf371b71 100644 --- a/docs/3/subscriptions/filtering-subscriptions.md +++ b/docs/3/subscriptions/filtering-subscriptions.md @@ -1,6 +1,8 @@ # Filtering Subscriptions -There are times when you'll need to filter out specific events based on the arguments provided by the client. To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. For instance, using the following example: +There are times when you'll need to filter out specific events based on the arguments provided by the client. +To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. +For instance, using the following example: ```graphql subscription onPostUpdated($post_id: ID!) { diff --git a/docs/3/subscriptions/getting-started.md b/docs/3/subscriptions/getting-started.md index 3891d610e2..98a802887a 100644 --- a/docs/3/subscriptions/getting-started.md +++ b/docs/3/subscriptions/getting-started.md @@ -1,11 +1,8 @@ # Subscriptions: Getting Started -Subscriptions allow GraphQL clients to observe specific events -and receive updates from the server when those events occur. +Subscriptions allow GraphQL clients to observe specific events and receive updates from the server when those events occur. -::: tip NOTE -Much of the credit should be given to the [Ruby implementation](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/overview.md) as they provided a great overview of how the backend should work. -::: +::: tip NOTE Much of the credit should be given to the [Ruby implementation](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/overview.md) as they provided a great overview of how the backend should work. ::: ## Setup diff --git a/docs/3/subscriptions/trigger-subscriptions.md b/docs/3/subscriptions/trigger-subscriptions.md index 0b20951ef4..f5421543b3 100644 --- a/docs/3/subscriptions/trigger-subscriptions.md +++ b/docs/3/subscriptions/trigger-subscriptions.md @@ -1,12 +1,10 @@ # Trigger Subscriptions -Now that clients can subscribe to a field, you will need to notify Lighthouse -when the underlying data has changed. +Now that clients can subscribe to a field, you will need to notify Lighthouse when the underlying data has changed. ## Broadcast Directive -The [`@broadcast`](../api-reference/directives.md#broadcast) -directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. +The [`@broadcast`](../api-reference/directives.md#broadcast) directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. ```graphql type Mutation { @@ -15,13 +13,11 @@ type Mutation { } ``` -You can reference the same subscription from multiple fields, or vice-versa -trigger multiple subscriptions from a single field. +You can reference the same subscription from multiple fields, or vice-versa trigger multiple subscriptions from a single field. ## Fire Subscriptions From Code -The `Subscription` class offers a utility method `broadcast` -that can be used to broadcast subscriptions from anywhere in your application. +The `Subscription` class offers a utility method `broadcast` that can be used to broadcast subscriptions from anywhere in your application. It accepts three parameters: @@ -29,8 +25,7 @@ It accepts three parameters: - `mixed $root` The result object you want to pass through - `bool $shouldQueue = null` Optional, overrides the default configuration `lighthouse.subscriptions.queue_broadcasts` -The following example shows how to trigger a subscription after an update -to the `Post` model. +The following example shows how to trigger a subscription after an update to the `Post` model. ```php $post->title = $newTitle; diff --git a/docs/3/testing/phpunit.md b/docs/3/testing/phpunit.md index 6a41015d36..c15df047bc 100644 --- a/docs/3/testing/phpunit.md +++ b/docs/3/testing/phpunit.md @@ -4,8 +4,8 @@ Lighthouse makes it easy to add automated tests through PHPUnit. ## Setup -Lighthouse offers some useful test helpers that make it easy to call your API -from within a PHPUnit test. Just add the `MakesGraphQLRequests` trait to your test class. +Lighthouse offers some useful test helpers that make it easy to call your API from within a PHPUnit test. +Just add the `MakesGraphQLRequests` trait to your test class. ```diff multipartGraphQL( diff --git a/docs/3/the-basics/directives.md b/docs/3/the-basics/directives.md index 2a281890ee..63f3a20fb1 100644 --- a/docs/3/the-basics/directives.md +++ b/docs/3/the-basics/directives.md @@ -1,16 +1,14 @@ # Directives -Assuming you read through the previous chapters, you should be familiar with the basics -of schema definition by now. +Assuming you read through the previous chapters, you should be familiar with the basics of schema definition by now. -You might have seen some funky extra bits in the schema definitions such as `@paginate`, -`@rules` or `@hasMany`. Those are called _directives_ and are the primary way -to add functionality to your GraphQL schema. +You might have seen some funky extra bits in the schema definitions such as `@paginate`, `@rules` or `@hasMany`. +Those are called _directives_ and are the primary way to add functionality to your GraphQL schema. ## Definition -Directives always begin with an `@` symbol, followed by an unique name. They may be used -at specified parts of the GraphQL schema. +Directives always begin with an `@` symbol, followed by a unique name. +They may be used at specified parts of the GraphQL schema. This example directive `@upperCase` may be used on field definitions to UPPERCASE the result. @@ -22,8 +20,8 @@ type Query { } ``` -Directives may also define arguments to enable a more flexible use, and they can -be used in multiple places, depending on the [specified directive location](https://facebook.github.io/graphql/June2018/#DirectiveLocation). +Directives may also define arguments to enable a more flexible use. +They can be used in multiple places, depending on the [specified directive location](https://facebook.github.io/graphql/June2018/#DirectiveLocation). ```graphql directive @append(text: String) on FIELD_DEFINITION | ARGUMENT_DEFINITION @@ -36,11 +34,9 @@ type Query { ## Usage -Lighthouse provides a plethora of built-in schema directives that are ready to -be consumed and can simply be used from within the schema. +Lighthouse provides a plethora of built-in schema directives that are ready to be consumed and can simply be used from within the schema. -The following example is quite dense, but it should give you an idea of what -directives are capable of. +The following example is quite dense, but it should give you an idea of what directives are capable of. ```graphql type Query { @@ -60,8 +56,6 @@ type Query { } ``` -Explore the docs to find out more or look into the [directives API reference](../api-reference/directives.md) -for a complete list of all available directives. +Explore the docs to find out more or look into the [directives API reference](../api-reference/directives.md) for a complete list of all available directives. -Implementing your own directives is a great way to add reusable functionality to your schema, -learn how you can [implement your own directives](../custom-directives/getting-started.md). +Implementing your own directives is a great way to add reusable functionality to your schema, learn how you can [implement your own directives](../custom-directives/getting-started.md). diff --git a/docs/3/the-basics/fields.md b/docs/3/the-basics/fields.md index a2b03c87dc..d2856a430c 100644 --- a/docs/3/the-basics/fields.md +++ b/docs/3/the-basics/fields.md @@ -2,15 +2,14 @@ The entrypoints to any GraphQL API are the fields of the root types `Query`, `Mutation` and `Subscription`. -_Every_ field has a function associated with it that is called when the field -is requested as part of a query. This function is called a **resolver**. +_Every_ field has a function associated with it that is called when the field is requested as part of a query. +This function is called a **resolver**. ## Hello World As is the tradition of our people, this section will teach you how to say "hello world!" through Lighthouse. -We start out by defining the simples possible schema: The root `Query` type -with a single field called `hello` that returns a `String`. +We start out by defining the simples possible schema: The root `Query` type with a single field called `hello` that returns a `String`. ```graphql type Query { @@ -21,8 +20,7 @@ type Query { This defines the shape of our data and informs the client what they can expect. You need to implement the actual resolver next. -By default, Lighthouse looks for a class with the capitalized name of the field in `App\GraphQL\Queries` -or `App\GraphQL\Mutations` and calls its `resolve` function with [the usual resolver arguments](../api-reference/resolvers.md#resolver-function-signature). +By default, Lighthouse looks for a class with the capitalized name of the field in `App\GraphQL\Queries` or `App\GraphQL\Mutations` and calls its `resolve` function with [the usual resolver arguments](../api-reference/resolvers.md#resolver-function-signature). In this case, our field is a query and is called `hello`, so we need to define our class as follows: @@ -40,9 +38,8 @@ class Hello } ``` -The easiest way to create such a class is to use the built in `artisan` commands -`lighthouse:query` and `lighthouse:mutation`. They both take a single argument: -the name of the field you want to generate. +The easiest way to create such a class is to use the built in `artisan` commands `lighthouse:query` and `lighthouse:mutation`. +They both take a single argument: the name of the field you want to generate. For example, this is how you generate a class for the field `hello`: @@ -71,8 +68,8 @@ This query will return the following response: As we learned, _every_ field has a resolver function associated with it. Just like functions, fields can take arguments to control their behaviour. -Let's construct a query that greets the user. We add a required argument `name` -that is used to construct the greeting. +Let's construct a query that greets the user. +We add a required argument `name` that is used to construct the greeting. ```graphql type Query { @@ -83,8 +80,7 @@ type Query { A minimal implementation of the field could look something like this. The skeleton for this class can be created using `php artisan lighthouse:query Greet`. -The second argument of the resolver function is an associative array of the -arguments that are passed to the query. +The second argument of the resolver function is an associative array of the arguments that are passed to the query. ```php ` -and including it in your schema. Lighthouse will look for Scalar types in a configurable -default namespace. +Define your own scalar types by running `php artisan lighthouse:scalar ` and including it in your schema. +Lighthouse will look for Scalar types in a configurable default namespace. ```graphql scalar ZipCode @@ -85,8 +83,8 @@ type Query { } ``` -In this example, the underlying values are actually integers. When the models are retrieved from -the database, the mapping is applied and the integers are converted to the defined string keys. +In this example, the underlying values are actually integers. +When the models are retrieved from the database, the mapping is applied and the integers are converted to the defined string keys. ```php return [ @@ -131,11 +129,9 @@ The PHP internal value of the field `ADMIN` will be `string('ADMIN')`. ### Native PHP definition -If you want to reuse enum definitions or constants from PHP, you can also -register a native PHP enum type [through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types). +If you want to reuse enum definitions or constants from PHP, you can also register a native PHP enum type [through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types). -Just define a [EnumType](https://webonyx.github.io/graphql-php/type-definitions/enums) and -register it: +Just define a [EnumType](https://webonyx.github.io/graphql-php/type-definitions/enums) and register it: ```php use GraphQL\Type\Definition\EnumType; @@ -166,8 +162,7 @@ $typeRegistry = app(TypeRegistry::class); $typeRegistry->register($episodeEnum); ``` -If you are using [BenSampo/laravel-enum](https://github.com/BenSampo/laravel-enum) -you can use a convenient wrapper to construct an enum type from it. +If you are using [BenSampo/laravel-enum](https://github.com/BenSampo/laravel-enum) you can use a convenient wrapper to construct an enum type from it. Given the following enum: @@ -187,8 +182,8 @@ final class UserType extends Enum } ``` -This is how you can register it in a ServiceProvider. Make sure to wrap it -in a `LaravelEnumType`. +This is how you can register it in a ServiceProvider. +Make sure to wrap it in a `LaravelEnumType`. ```php ` to create -a custom interface class. It is automatically put in the default namespace where Lighthouse can discover it by itself. +You can also provide a custom type resolver. +Run `php artisan lighthouse:interface ` to create a custom interface class. +It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) ## Union A Union is an abstract type that simply enumerates other Object Types. -They are similar to interfaces in that they can return different types, but they can not -have fields defined. +They are similar to interfaces in that they can return different types, but they can not have fields defined. ```graphql union Person = User | Employee @@ -299,10 +291,8 @@ type Employee { } ``` -Just like Interfaces, you need a way to determine the concrete Object Type for a Union, -based on the resolved value. If the default type resolver does not work for you, define your -own using `php artisan lighthouse:union `. +Just like Interfaces, you need a way to determine the concrete Object Type for a Union, based on the resolved value. +If the default type resolver does not work for you, define your own using `php artisan lighthouse:union `. It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) diff --git a/docs/4/api-reference/commands.md b/docs/4/api-reference/commands.md index ef2b2022e5..0b80e68d4a 100644 --- a/docs/4/api-reference/commands.md +++ b/docs/4/api-reference/commands.md @@ -1,7 +1,7 @@ # Artisan Commands -Lighthouse provides some convenient artisan commands. All of them -are namespaced under `lighthouse`. +Lighthouse provides some convenient artisan commands. +All of them are namespaced under `lighthouse`. ## cache @@ -21,10 +21,8 @@ Create a class for a custom schema directive. php artisan lighthouse:directive -Use the `--type`, `--field` and `--argument` options to create type, field and -argument directives, respectively. The command will then ask you which -interfaces the directive should implement and add the required method stubs and -imports for you. +Use the `--type`, `--field` and `--argument` options to create type, field and argument directives, respectively. +The command will then ask you which interfaces the directive should implement and add the required method stubs and imports for you. ## ide-helper @@ -38,8 +36,7 @@ This will create the following files: - `programmatic-types.graphql`: Schema definitions for programmatically registered types, if you have any - `_lighthouse_ide_helper.php`: Class definitions for some magical PHP, such as the `TestResponse` mixin -A great way to keep up to date with your current version of Lighthouse -is to add this script to your `composer.json`: +A great way to keep up to date with your current version of Lighthouse is to add this script to your `composer.json`: ```json "scripts": { @@ -69,12 +66,10 @@ Compile the GraphQL schema and print the result. php artisan lighthouse:print-schema -This can be quite useful, as the root `.graphql` files do not necessarily -contains the whole schema. Schema imports, native PHP types and schema manipulation -may influence the final schema. +This can be quite useful, as the root `.graphql` files do not necessarily contains the whole schema. +Schema imports, native PHP types and schema manipulation may influence the final schema. -Use the `-W` / `--write` option to output the schema to the default file storage -(usually `storage/app`) as `lighthouse-schema.graphql`. +Use the `-W` / `--write` option to output the schema to the default file storage (usually `storage/app`) as `lighthouse-schema.graphql`. You can output your schema in JSON format by using the `--json` flag. diff --git a/docs/4/api-reference/directives.md b/docs/4/api-reference/directives.md index e2dd2437e7..e0777370fd 100644 --- a/docs/4/api-reference/directives.md +++ b/docs/4/api-reference/directives.md @@ -10,8 +10,8 @@ type Query { } ``` -This assumes your model has the same name as the type you are returning and is defined -in the default model namespace `App`. [You can change this configuration](../getting-started/configuration.md). +This assumes your model has the same name as the type you are returning and is defined in the default model namespace `App`. +[You can change this configuration](../getting-started/configuration.md). ### Definition @@ -67,8 +67,7 @@ directive @auth( ### Examples -If you need to use a guard besides the default to resolve the authenticated user, -you can pass the guard name as the `guard` argument +If you need to use a guard besides the default to resolve the authenticated user, you can pass the guard name as the `guard` argument ```graphql type Query { @@ -127,8 +126,7 @@ directive @belongsTo( ### Examples -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type Post { @@ -212,8 +210,7 @@ directive @belongsToMany( ### Examples -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type User { @@ -221,13 +218,11 @@ type User { } ``` -When using the connection `type` argument, you may create your own -[Edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) which -may have fields that resolve from the model [pivot](https://laravel.com/docs/eloquent-relationships#many-to-many) -data. You may also add a custom field resolver for fields you want to resolve yourself. +When using the connection `type` argument, you may create your own [Edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) which may have fields that resolve from the model [pivot](https://laravel.com/docs/eloquent-relationships#many-to-many) data. +You may also add a custom field resolver for fields you want to resolve yourself. -You may either specify the edge using the `edgetype` argument, or it will automatically -look for a {type}Edge type to be defined. In this case it would be `RoleEdge`. +You may either specify the edge using the `edgetype` argument, or it will automatically look for a {type}Edge type to be defined. +In this case it would be `RoleEdge`. ```graphql type User { @@ -290,8 +285,7 @@ directive @broadcast( ### Examples -You may override the default queueing behaviour from the configuration by -passing the `shouldQueue` argument. +You may override the default queueing behaviour from the configuration by passing the `shouldQueue` argument. ```graphql type Mutation { @@ -312,8 +306,7 @@ type Query { } ``` -You must point to a `method` which will receive the builder instance -and the argument value and can apply additional constraints to the query. +You must point to a `method` which will receive the builder instance and the argument value and can apply additional constraints to the query. ```php namespace App; @@ -387,8 +380,7 @@ directive @cache( ### Examples -You can set an expiration time in seconds -if you want to invalidate the cache after a while. +You can set an expiration time in seconds if you want to invalidate the cache after a while. ```graphql type Query { @@ -473,8 +465,7 @@ directive @can( ) on FIELD_DEFINITION ``` -The name of the returned Type `Post` is used as the Model class, however you may overwrite this by -passing the `model` argument. +The name of the returned Type `Post` is used as the Model class, however you may overwrite this by passing the `model` argument. ```graphql type Mutation { @@ -524,8 +515,7 @@ type Query { } ``` -A custom complexity function may look like the following, -refer to the [complexity function signature](resolvers.md#complexity-function-signature). +A custom complexity function may look like the following, refer to the [complexity function signature](resolvers.md#complexity-function-signature). ```php namespace App\Security; @@ -608,8 +598,7 @@ type Mutation { } ``` -If you are using a single input object as an argument, you must tell Lighthouse -to spread out the nested values before applying it to the resolver. +If you are using a single input object as an argument, you must tell Lighthouse to spread out the nested values before applying it to the resolver. ```graphql type Mutation { @@ -621,8 +610,7 @@ input CreatePostInput { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, or is located in a non-default namespace, set it with the `model` argument. ```graphql type Mutation { @@ -679,8 +667,7 @@ type Mutation { ``` You can also delete multiple models at once. -Define a field that takes a list of IDs and returns a collection of the -deleted models. +Define a field that takes a list of IDs and returns a collection of the deleted models. _In contrast to Laravel mass updates, this does trigger model events._ @@ -690,8 +677,7 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, or is located in a non-default namespace, set it with the `model` argument. ```graphql type Mutation { @@ -708,9 +694,7 @@ type Mutation { } ``` -If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or -`MorphTo` relationship, you can just pass a Boolean instead of an ID, as there is only one -possible model that can be deleted. +If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or `MorphTo` relationship, you can just pass a Boolean instead of an ID, as there is only one possible model that can be deleted. ```graphql type Mutation { @@ -721,9 +705,8 @@ type Mutation { ## @deprecated -You can mark fields as deprecated by adding the [@deprecated](#deprecated) directive and providing a -`reason`. Deprecated fields are not included in introspection queries unless -requested and they can still be queried by clients. +You can mark fields as deprecated by adding the [@deprecated](#deprecated) directive and providing a `reason`. +Deprecated fields are not included in introspection queries unless requested and they can still be queried by clients. ```graphql type Query { @@ -785,9 +768,8 @@ directive @field( ### Examples -If your field is defined on the root types `Query` or `Mutation`, you can take advantage -of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). The following -will look for a class in `App\GraphQL\Queries` by default. +If your field is defined on the root types `Query` or `Mutation`, you can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). +The following will look for a class in `App\GraphQL\Queries` by default. ```graphql type Query { @@ -795,8 +777,8 @@ type Query { } ``` -Be aware that resolvers are not limited to root fields. A resolver can be used for basic tasks -such as transforming the value of scalar fields, e.g. reformat a date. +Be aware that resolvers are not limited to root fields. +A resolver can be used for basic tasks such as transforming the value of scalar fields, e.g. reformat a date. ```graphql type User { @@ -947,8 +929,8 @@ enum Role { } ``` -You do not need this directive if the internal value of each enum key -is an identical string. [Read more about enum types](../the-basics/types.md#enum) +You do not need this directive if the internal value of each enum key is an identical string. +[Read more about enum types](../the-basics/types.md#enum) ## @eq @@ -974,8 +956,7 @@ directive @eq( ### Examples -If the name of the argument does not match the database column, -pass the actual column name as the `key`. +If the name of the argument does not match the database column, pass the actual column name as the `key`. ```graphql type User { @@ -986,8 +967,7 @@ type User { ## @event Fire an event after a mutation has taken place. -It requires the `dispatch` argument that should be -the class name of the event you want to fire. +It requires the `dispatch` argument that should be the class name of the event you want to fire. ```graphql type Mutation { @@ -1023,8 +1003,7 @@ type User { } ``` -Instead of the original ID, the `id` field will now return a base64-encoded String -that globally identifies the User and can be used for querying the `node` endpoint. +Instead of the original ID, the `id` field will now return a base64-encoded String that globally identifies the User and can be used for querying the `node` endpoint. ### Definition @@ -1052,11 +1031,9 @@ type Mutation { } ``` -The field resolver will receive the decoded version of the passed `id`, -split into type and ID. +The field resolver will receive the decoded version of the passed `id`, split into type and ID. -You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global ids. +You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global ids. ## @guard @@ -1167,8 +1144,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -1208,8 +1184,7 @@ directive @hasOne( ### Examples -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -1241,11 +1216,10 @@ directive @in( ## @include -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and it should be noted this directive is a client side and should not be included in your schema. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and it should be noted this directive is a client side and should not be included in your schema. -Only includes a field in response if the value passed into this directive is true. This directive is one of the core -directives in the GraphQL spec. +Only includes a field in response if the value passed into this directive is true. +This directive is one of the core directives in the GraphQL spec. ```graphql directive @include( @@ -1259,8 +1233,8 @@ directive @include( ### Examples -The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments, -and allows for conditional inclusion during execution as described by the `if` argument. +The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional inclusion during execution as described by the `if` argument. In this example experimentalField will only be queried if the variable \$someTest has the value true @@ -1282,8 +1256,7 @@ type Mutation { } ``` -This is useful to ensure that the authenticated user's `id` is -automatically used for creating new models and can not be manipulated. +This is useful to ensure that the authenticated user's `id` is automatically used for creating new models and can not be manipulated. ### Definition @@ -1307,8 +1280,7 @@ directive @inject( ### Examples -If you are using an Input Object as an argument, you can use dot notation to -set a nested argument. +If you are using an Input Object as an argument, you can use dot notation to set a nested argument. ```graphql type Mutation { @@ -1322,8 +1294,7 @@ type Mutation { Use a custom resolver to determine the concrete type of an interface. -Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding -to use this directive, you probably don't need it. +Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding to use this directive, you probably don't need it. Set the `resolveType` argument to a function that returns the implementing Object Type. @@ -1334,8 +1305,8 @@ interface Commentable } ``` -The function receives the value of the parent field as its single argument and must -return an Object Type. You can get the appropriate Object Type from Lighthouse's type registry. +The function receives the value of the parent field as its single argument and must return an Object Type. +You can get the appropriate Object Type from Lighthouse's type registry. ```php purchasedItemsCount(2017, null) ## @middleware -**DEPRECATED** -Use [@guard](#guard) or custom [`FieldMiddleware`](../custom-directives/field-directives.md#fieldmiddleware) instead. +**DEPRECATED** Use [@guard](#guard) or custom [`FieldMiddleware`](../custom-directives/field-directives.md#fieldmiddleware) instead. ```graphql """ @@ -1503,8 +1472,8 @@ directive @middleware( ) on FIELD_DEFINITION | OBJECT ``` -You can define middleware just like you would in Laravel. Pass in either a fully qualified -class name, an alias or a middleware group - or any combination of them. +You can define middleware just like you would in Laravel. +Pass in either a fully qualified class name, an alias or a middleware group - or any combination of them. ```graphql type Query { @@ -1531,9 +1500,8 @@ extend type Query { } ``` -Other then global middleware defined in the [configuration](../getting-started/configuration.md), field middleware -only applies to the specific field it is defined on. This has the benefit of limiting errors -to particular fields and not failing an entire request if a middleware fails. +Other then global middleware defined in the [configuration](../getting-started/configuration.md), field middleware only applies to the specific field it is defined on. +This has the benefit of limiting errors to particular fields and not failing an entire request if a middleware fails. There are a few caveats to field middleware though: @@ -1543,8 +1511,7 @@ There are a few caveats to field middleware though: but rather the slice of data that the particular field returned. - The `terminate` method of field middleware is not called. -If the middleware needs to be aware of GraphQL specifics, such as the resolver arguments, -it is often more suitable to define a custom field directive. +If the middleware needs to be aware of GraphQL specifics, such as the resolver arguments, it is often more suitable to define a custom field directive. ## @model @@ -1707,8 +1674,7 @@ union Imageable = Post | User Redefine the default namespaces used in other directives. -The following example applies the namespace `App\Blog` -to the [@field](#field) directive used on the `posts` field. +The following example applies the namespace `App\Blog` to the [@field](#field) directive used on the `posts` field. ```graphql type Query { @@ -1730,9 +1696,8 @@ directive @namespace on FIELD_DEFINITION | OBJECT ### Examples -When used upon an object type or an object type extension, the namespace -applies to fields of the type as well. This allows you to specify -a common namespace for a group of fields. +When used upon an object type or an object type extension, the namespace applies to fields of the type as well. +This allows you to specify a common namespace for a group of fields. ```graphql extend type Query @namespace(field: "App\\Blog") { @@ -1831,8 +1796,7 @@ directive @node( ) on OBJECT ``` -Lighthouse defaults to resolving types through the underlying model, -for example by calling `User::find($id)`. +Lighthouse defaults to resolving types through the underlying model, for example by calling `User::find($id)`. ```graphql type User @node { @@ -1848,8 +1812,7 @@ type Country @node(resolver: "App\\Countries@byId") { } ``` -The `resolver` argument has to specify a function which will be passed the -decoded `id` and resolves to a result. +The `resolver` argument has to specify a function which will be passed the decoded `id` and resolves to a result. ```php public function byId($id): array { @@ -1864,8 +1827,7 @@ public function byId($id): array { ### Definition -Behind the scenes, Lighthouse will decode the global id sent from the client -to find the model by it's primary id in the database. +Behind the scenes, Lighthouse will decode the global id sent from the client to find the model by it's primary id in the database. ## @notIn @@ -1918,8 +1880,8 @@ directive @orderBy( **It is recommended to change the `lighthouse.php` setting `orderBy` when using this directive.** -Use it on a field argument of an Eloquent query. The type of the argument -can be left blank as `_` , as it will be automatically generated. +Use it on a field argument of an Eloquent query. +The type of the argument can be left blank as `_` , as it will be automatically generated. ```graphql type Query { @@ -1927,8 +1889,8 @@ type Query { } ``` -Lighthouse will automatically generate an input that takes enumerated column names, -together with the `SortOrder` enum, and add that to your schema. Here is how it looks: +Lighthouse will automatically generate an input that takes enumerated column names, together with the `SortOrder` enum, and add that to your schema. +Here is how it looks: ```graphql "Allows ordering a list of records." @@ -2083,8 +2045,7 @@ And can be queried like this: ### Pagination type -The `type` of pagination defaults to `paginator`, but may also be set to a Relay -compliant `connection`. +The `type` of pagination defaults to `paginator`, but may also be set to a Relay compliant `connection`. > Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -2144,9 +2105,8 @@ query { ### Limit maximum count -Lighthouse allows you to specify a global maximum for the number of items a user -can request through pagination through the config. You may also overwrite this -per field with the `maxCount` argument: +Lighthouse allows you to specify a global maximum for the number of items a user can request through pagination through the config. +You may also overwrite this per field with the `maxCount` argument: ```graphql type Query { @@ -2156,8 +2116,8 @@ type Query { ### Overwrite model -By default, Lighthouse looks for an Eloquent model in the configured default namespace, with the same -name as the returned type. You can overwrite this by setting the `model` argument. +By default, Lighthouse looks for an Eloquent model in the configured default namespace, with the same name as the returned type. +You can overwrite this by setting the `model` argument. ```graphql type Query { @@ -2216,8 +2176,7 @@ directive @rename( ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -This can often be useful to ensure consistent naming of your schema -without having to change the underlying models. +This can often be useful to ensure consistent naming of your schema without having to change the underlying models. ```graphql type User { @@ -2400,12 +2359,10 @@ type Query { } ``` -The `search()` method of the model is called with the value of the argument, -using the driver you configured for [Laravel Scout](https://laravel.com/docs/scout). +The `search()` method of the model is called with the value of the argument, using the driver you configured for [Laravel Scout](https://laravel.com/docs/scout). The [@search](#search) directive does not work in combination with other filter directives. -The usual query builder `Eloquent\Builder` will be replaced by a `Scout\Builder`, -which does not support the same methods and operations. +The usual query builder `Eloquent\Builder` will be replaced by a `Scout\Builder`, which does not support the same methods and operations. ### Definition @@ -2434,8 +2391,7 @@ type Query { ## @skip -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and it should be noted this directive is a client side directive and should not be included in your schema. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and it should be noted this directive is a client side directive and should not be included in your schema. ### Definition @@ -2451,8 +2407,8 @@ directive @skip( ### Examples -The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional -exclusion during execution as described by the if argument. +The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional exclusion during execution as described by the if argument. In this example experimentalField will only be queried if the variable \$someTest has the value `false`. @@ -2534,8 +2490,7 @@ mutation { } ``` -Internally, the arguments will be transformed into a flat structure before -they are passed along to the resolver: +Internally, the arguments will be transformed into a flat structure before they are passed along to the resolver: ```php [ @@ -2545,16 +2500,15 @@ they are passed along to the resolver: ] ``` -Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/argument-directives.md) -have been applied, e.g. validation, transformation. +Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/argument-directives.md) have been applied, e.g. validation, transformation. ## @subscription Reference a class to handle the broadcasting of a subscription to clients. The given class must extend `\Nuwave\Lighthouse\Schema\Types\GraphQLSubscription`. -If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md) -you do not need this directive. It is only useful if you need to override the default namespace. +If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md) you do not need this directive. +It is only useful if you need to override the default namespace. ```graphql type Subscription { @@ -2589,8 +2543,7 @@ directive @trashed on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION The most convenient way to use this directive is through [@softDeletes](#softdeletes). -If you want to add it manually, make sure the argument is of the -enum type `Trashed`: +If you want to add it manually, make sure the argument is of the enum type `Trashed`: ```graphql type Query { @@ -2621,8 +2574,7 @@ directive @trim on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION Use a custom function to determine the concrete type of unions. -Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding -to use this directive, you probably don't need it. +Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding to use this directive, you probably don't need it. ```graphql type User { @@ -2638,8 +2590,7 @@ union Person @union(resolveType: "App\\GraphQL\\Unions\\Person@resolveType") = | Employee ``` -The function receives the value of the parent field as its single argument and must -resolve an Object Type from Lighthouse's `TypeRegistry`. +The function receives the value of the parent field as its single argument and must resolve an Object Type from Lighthouse's `TypeRegistry`. ```php listen( @@ -17,8 +15,7 @@ app('events')->listen( ); ``` -When your schema is defined within files and you want to use `#import` to combine them, -you can use the `\Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: +When your schema is defined within files and you want to use `#import` to combine them, you can use the `\Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: ```php $stitcher = new \Nuwave\Lighthouse\Schema\Source\SchemaStitcher(__DIR__ . '/path/to/schema.graphql'); @@ -29,11 +26,9 @@ return $stitcher->getSchemaString(); While Lighthouse is an SDL-first GraphQL server, you can also use native PHP type definitions. -Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) -on how to define types. +Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) on how to define types. -Note that you will not have access to a large portion of Lighthouse functionality -that is provided through server-side directives and the definition is much more verbose. +Note that you will not have access to a large portion of Lighthouse functionality that is provided through server-side directives and the definition is much more verbose. Because of this, we do not recommend you use native PHP types for complex object types. diff --git a/docs/4/digging-deeper/client-directives.md b/docs/4/digging-deeper/client-directives.md index d954726f8b..be2439efc6 100644 --- a/docs/4/digging-deeper/client-directives.md +++ b/docs/4/digging-deeper/client-directives.md @@ -4,17 +4,16 @@ Client directives allow clients to change the behaviour of query execution. > Client directives must not be used within your schema definition. -The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) -mentions two client directives: [@skip](#skip) and [@include](#include). +The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) mentions two client directives. +[@skip](#skip) and [@include](#include). Both are built-in to Lighthouse and work out-of-the-box. ## @skip -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional -exclusion during execution as described by the `if` argument. +The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional exclusion during execution as described by the `if` argument. ```graphql directive @skip( @@ -36,11 +35,10 @@ query myQuery($someTest: Boolean) { ## @include -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments, -and allows for conditional inclusion during execution as described by the `if` argument. +The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional inclusion during execution as described by the `if` argument. ```graphql directive @include( @@ -74,19 +72,17 @@ directive @example( ``` By itself, a custom client directive does not do anything. -Lighthouse provides a class to retrieve information about where client directives -were placed in the query and what arguments were given to them. +Lighthouse provides a class to retrieve information about where client directives were placed in the query and what arguments were given to them. ```php $clientDirective = new \Nuwave\Lighthouse\ClientDirectives\ClientDirective('example'); ``` -The most common use case for a client directive is to place it on a field. There is a caveat -to working with this that is unintuitive at first: There might be multiple nodes referencing a single -field, and each of those may or may not have the client directive set, with possibly different arguments. +The most common use case for a client directive is to place it on a field. +There is a caveat to working with this that is unintuitive at first: There might be multiple nodes referencing a single field. +Each of those may or may not have the client directive set, with possibly different arguments. -The following example illustrates how a field `foo` can be referenced three times with different -configurations of a client directive: +The following example illustrates how a field `foo` can be referenced three times with different configurations of a client directive: ```graphql { @@ -98,8 +94,7 @@ configurations of a client directive: } ``` -You can get all arguments for every node that is referencing the field you are currently -resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): +You can get all arguments for every node that is referencing the field you are currently resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): ```php $arguments = $clientDirective->forField($resolveInfo); @@ -116,8 +111,8 @@ For the example query above, it will look like this: ] ``` -You are then free to implement whatever logic on top of that. Some client directives may require -only one field node to have it set, whereas others might require all of them to have the same configuration. +You are then free to implement whatever logic on top of that. +Some client directives may require only one field node to have it set, whereas others might require all of them to have the same configuration. > There are other locations where client directives may be used on: https://spec.graphql.org/draft/#ExecutableDirectiveLocation > You can add a PR to Lighthouse if you need them. diff --git a/docs/4/digging-deeper/error-handling.md b/docs/4/digging-deeper/error-handling.md index 2bd9b053f3..9f69754073 100644 --- a/docs/4/digging-deeper/error-handling.md +++ b/docs/4/digging-deeper/error-handling.md @@ -1,26 +1,23 @@ # Error Handling -Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**, -so you can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). +Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**. +You can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). ## User-friendly Errors -In a production setting, error messages should not be shown to the user by default -to prevent information leaking. In some cases however, you may want to display an -explicit error message to the user. +In a production setting, error messages should not be shown to the user by default to prevent information leaking. +In some cases however, you may want to display an explicit error message to the user. -**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface, that can -be implemented by Exceptions to control how they are rendered to the client. +**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface. +Can be implemented by Exceptions to control how they are rendered to the client. Head over their [Error Handling docs](https://webonyx.github.io/graphql-php/error-handling) to learn more. ## Additional Error Information -The interface [`\Nuwave\Lighthouse\Exceptions\RendersErrorsExtensions`](https://github.com/nuwave/lighthouse/blob/master/src/Exceptions/RendersErrorsExtensions.php) -may be extended to add more information then just an error message to the rendered error output. +The interface [`\Nuwave\Lighthouse\Exceptions\RendersErrorsExtensions`](https://github.com/nuwave/lighthouse/blob/master/src/Exceptions/RendersErrorsExtensions.php) may be extended to add more information then just an error message to the rendered error output. -Let's say you want to have a custom exception type that contains information about -the reason why the exception was thrown. +Let's say you want to have a custom exception type that contains information about the reason why the exception was thrown. ```php Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -15,11 +13,10 @@ type Query { } ``` -This automatically converts the type definition into a relay connection and constructs -the appropriate queries via the underlying Eloquent model. +This automatically converts the type definition into a relay connection and constructs the appropriate queries via the underlying Eloquent model. -Connections can also be used for sub-fields of a type, given they are defined as a HasMany-Relationship -in Eloquent. Use the [@hasMany](../api-reference/directives.md#hasmany) directive. +Connections can also be used for sub-fields of a type, given they are defined as a HasMany-Relationship in Eloquent. +Use the [@hasMany](../api-reference/directives.md#hasmany) directive. ```graphql type User { @@ -30,8 +27,7 @@ type User { ## Global Object Identification -You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global ids. +You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global ids. [Global Object Identification](https://facebook.github.io/relay/graphql/objectidentification.htm) @@ -41,8 +37,7 @@ own mechanism of encoding/decoding global ids. ## Input Object Mutations -Lighthouse makes it easy to follow the principle of using a -single field argument called `input`, just use the [@spread](../api-reference/directives.md#spread) directive. +Lighthouse makes it easy to follow the principle of using a single field argument called `input`, just use the [@spread](../api-reference/directives.md#spread) directive. ```graphql type Mutation { diff --git a/docs/4/digging-deeper/schema-organisation.md b/docs/4/digging-deeper/schema-organisation.md index 57cf45f788..70172a6426 100644 --- a/docs/4/digging-deeper/schema-organisation.md +++ b/docs/4/digging-deeper/schema-organisation.md @@ -24,8 +24,8 @@ type Query { #import user.graphql ``` -Imports always begin on a separate line with `#import`, followed by the relative path -to the imported file. The contents of `user.graphql` are pasted in the final schema. +Imports always begin on a separate line with `#import`, followed by the relative path to the imported file. +The contents of `user.graphql` are pasted in the final schema. ```graphql type Query { @@ -79,8 +79,8 @@ type Query { } ``` -Now you want to add a few queries to actually fetch posts. You could add them to the main `Query` type -in your main file, but that spreads the definition apart, and could also grow quite large over time. +Now you want to add a few queries to actually fetch posts. +You could add them to the main `Query` type in your main file, but that spreads the definition apart, and could also grow quite large over time. Another way would be to extend the `Query` type and colocate the type definition with its Queries in `post.graphql`. @@ -100,5 +100,4 @@ The fields in the `extend type` definition are merged with those of the original ### Extending other types Apart from object types `type`, you can also extend `input`, `interface` and `enum` types. -Lighthouse will merge the fields (or values) with the original definition and always -produce a single type in the final schema. +Lighthouse will merge the fields (or values) with the original definition and always produce a single type in the final schema. diff --git a/docs/4/eloquent/complex-where-conditions.md b/docs/4/eloquent/complex-where-conditions.md index 2fecb8b7f3..a1bba5a173 100644 --- a/docs/4/eloquent/complex-where-conditions.md +++ b/docs/4/eloquent/complex-where-conditions.md @@ -1,9 +1,7 @@ # Complex Where Conditions -Adding query conditions ad-hoc can be cumbersome and limiting when you require -many different ways to filter query results. -Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients -and allow them to apply complex, dynamic WHERE conditions to queries. +Adding query conditions ad-hoc can be cumbersome and limiting when you require many different ways to filter query results. +Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients and allow them to apply complex, dynamic WHERE conditions to queries. ## Setup @@ -23,8 +21,7 @@ Install the dependency [mll-lab/graphql-php-scalars](https://github.com/mll-lab/ ## Usage -You can use this feature through a set of schema directives that enhance fields -with advanced filter capabilities. +You can use this feature through a set of schema directives that enhance fields with advanced filter capabilities. ### @whereConditions @@ -67,8 +64,8 @@ type Person { } ``` -Lighthouse automatically generates definitions for an `Enum` type and an `Input` type -that are restricted to the defined columns, so you do not have to specify them by hand. +Lighthouse automatically generates definitions for an `Enum` type and an `Input` type that are restricted to the defined columns. +You do not have to specify them by hand. The blank type named `_` will be changed to the actual type. Here are the types that will be included in the compiled schema: @@ -100,8 +97,8 @@ enum PeopleWhereColumn { } ``` -Alternatively to the `columns` argument, you can also use `columnsEnum` in case you -want to re-use a list of allowed columns. Here's how your schema could look like: +Alternatively to the `columns` argument, you can also use `columnsEnum` in case you want to re-use a list of allowed columns. +Here's how your schema could look like: ```graphql type Query { @@ -127,8 +124,7 @@ Instead of creating enums for the allowed columns, it will simply use the existi It is recommended to either use the `columns` or the `columnsEnum` argument. When you don't define any allowed columns, clients can specify arbitrary column names as a `String`. -This approach should by taken with care, as it carries -potential performance and security risks and offers little type safety. +This approach should by taken with care, as it carries potential performance and security risks and offers little type safety. A simple query for a person who is exactly 42 years old would look like this: @@ -140,8 +136,7 @@ A simple query for a person who is exactly 42 years old would look like this: } ``` -Note that the operator defaults to `EQ` (`=`) if not given, so you could -also omit it from the previous example and get the same result. +Note that the operator defaults to `EQ` (`=`) if not given, so you could also omit it from the previous example and get the same result. The following query gets actors over age 37 who either have red hair or are at least 150cm: @@ -166,8 +161,8 @@ The following query gets actors over age 37 who either have red hair or are at l } ``` -Some operators require passing lists of values - or no value at all. The following -query gets people that have no hair and blue-ish eyes: +Some operators require passing lists of values - or no value at all. +The following query gets people that have no hair and blue-ish eyes: ```graphql { @@ -228,8 +223,7 @@ directive @whereHasConditions( ) on ARGUMENT_DEFINITION ``` -This directive works very similar to [@whereConditions](#whereconditions), except that -the conditions are applied to a relation sub query: +This directive works very similar to [@whereConditions](#whereconditions), except that the conditions are applied to a relation sub query: ```graphql type Query { @@ -272,8 +266,7 @@ enum PeopleHasRoleColumn { } ``` -A simple query for a person who has an access level of at least 5, through one of -their roles, looks like this: +A simple query for a person who has an access level of at least 5, through one of their roles, looks like this: ```graphql { @@ -308,10 +301,10 @@ This query would retrieve all persons, no matter if they have a role or not: ## Custom operator If Lighthouse's default `SQLOperator` does not fit your use case, you can register a custom operator class. -This may be necessary if your database uses different SQL operators then Lighthouse's default or you -want to extend/restrict the allowed operators. +This may be necessary if your database uses different SQL operators then Lighthouse's default or you want to extend/restrict the allowed operators. -First create a class that implements `\Nuwave\Lighthouse\WhereConditions\Operator`. For example: +First create a class that implements `\Nuwave\Lighthouse\WhereConditions\Operator`. +For example: ```php namespace App\GraphQL; diff --git a/docs/4/eloquent/getting-started.md b/docs/4/eloquent/getting-started.md index cc67fc738b..dce064f6fd 100644 --- a/docs/4/eloquent/getting-started.md +++ b/docs/4/eloquent/getting-started.md @@ -26,8 +26,7 @@ type Query { } ``` -The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as -the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. +The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. The following query: @@ -55,8 +54,7 @@ Will return the following result: ## Pagination -You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to -query a large list of models in chunks. +You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to query a large list of models in chunks. ```graphql type Query { @@ -96,8 +94,7 @@ And can be queried like this: ## Adding Query Constraints -Lighthouse provides built-in directives to enhance your queries by giving -additional query capabilities to the client. +Lighthouse provides built-in directives to enhance your queries by giving additional query capabilities to the client. The following field definition allows you to fetch a single User by ID. @@ -131,8 +128,7 @@ And, if a result is found, receive a result like this: ## Local Scopes -[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models -to specify reusable query constraints. +[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models to specify reusable query constraints. ```php use Illuminate\Database\Eloquent\Builder; @@ -147,8 +143,7 @@ class User extends Model } ``` -Directives that query models, such as [@all](../api-reference/directives.md#all) -or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: +Directives that query models, such as [@all](../api-reference/directives.md#all) or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: ```graphql type Query { @@ -240,8 +235,7 @@ The update may fail to find the model you provided and return `null`: ## Upsert -Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with -a given `id` or create it if it does not exist. +Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with a given `id` or create it if it does not exist. ```graphql type Mutation { @@ -276,7 +270,8 @@ mutation { ## Delete -Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. Dangerously easy. +Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. +Dangerously easy. ```graphql type Mutation { @@ -294,7 +289,8 @@ mutation { } ``` -This mutation will return the deleted object, so you will have a last chance to look at the data. Use it wisely. +This mutation will return the deleted object, so you will have a last chance to look at the data. +Use it wisely. ```json { diff --git a/docs/4/eloquent/nested-mutations.md b/docs/4/eloquent/nested-mutations.md index f2513144f7..e87e571aeb 100644 --- a/docs/4/eloquent/nested-mutations.md +++ b/docs/4/eloquent/nested-mutations.md @@ -1,12 +1,11 @@ # Nested Mutations -Lighthouse allows you to create, update or delete models and their associated relationships, -all in one single mutation. This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). +Lighthouse allows you to create, update or delete models and their associated relationships, all in one single mutation. +This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). ## Return Types Required -You have to define return types on your relationship methods so that Lighthouse -can detect them. +You have to define return types on your relationship methods so that Lighthouse can detect them. ```php use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -28,20 +27,17 @@ class Post extends Model ## Partial Failure By default, all mutations are wrapped in a database transaction. -If any of the nested operations fail, the whole mutation is aborted -and no changes are written to the database. +If any of the nested operations fail, the whole mutation is aborted and no changes are written to the database. You can change this setting [in the configuration](../getting-started/configuration.md). ## Polymorphic Relation Limitations -Because the GraphQL Specification does not support polymorphic Input types (yet), -the available functionality is limited. +Because the GraphQL Specification does not support polymorphic Input types (yet), the available functionality is limited. -It is not possible to have an argument that can contain different types, which -would be necessary to pass the attributes the different related models might have. -For now, we can only support cases where the input type does not change across related -models, e.g. connecting through an ID, disconnecting or deleting the relation. +It is not possible to have an argument that can contain different types. +Would be necessary to pass the attributes the different related models might have. +For now, we can only support cases where the input type does not change across related models, e.g. connecting through an ID, disconnecting or deleting the relation. See [this issue](https://github.com/nuwave/lighthouse/issues/900) for further discussion. @@ -55,8 +51,7 @@ type Mutation { } ``` -The mutation takes a single argument `input` that contains data about -the Post you want to create. +The mutation takes a single argument `input` that contains data about the Post you want to create. ```graphql input CreatePostInput { @@ -65,8 +60,7 @@ input CreatePostInput { } ``` -The first argument `title` is a value of the `Post` itself and corresponds -to a column in the database. +The first argument `title` is a value of the `Post` itself and corresponds to a column in the database. The second argument `author` is named just like the relationship method that is defined on the `Post` model. A nested `BelongsTo` relationship exposes the following operations: @@ -99,8 +93,7 @@ input CreateUserInput { } ``` -To create a new model and connect it to an existing model, -just pass the ID of the model you want to associate. +To create a new model and connect it to an existing model, just pass the ID of the model you want to associate. ```graphql mutation { @@ -128,8 +121,7 @@ Lighthouse will create a new `Post` and associate an `User` with it. } ``` -If the related model does not exist yet, you can also -create a new one. +If the related model does not exist yet, you can also create a new one. ```graphql mutation { @@ -158,8 +150,7 @@ mutation { ``` When issuing an update, you can also allow the user to remove a relation. -Both `disconnect` and `delete` remove the association to the author, -but `delete` also removes the author model itself. +Both `disconnect` and `delete` remove the association to the author, but `delete` also removes the author model itself. ```graphql type Mutation { @@ -183,8 +174,7 @@ input UpdateUserBelongsTo { ``` You must pass a truthy value to `disconnect` and `delete` for them to actually run. -This structure was chosen as it is consistent with updating `BelongsToMany` relationships -and allows the query string to be mostly static, taking a variable value to control its behaviour. +This structure was chosen as it is consistent with updating `BelongsToMany` relationships and allows the query string to be mostly static, taking a variable value to control its behaviour. ```graphql mutation UpdatePost($disconnectAuthor: Boolean) { @@ -203,8 +193,7 @@ mutation UpdatePost($disconnectAuthor: Boolean) { } ``` -The `author` relationship will only be disconnected if the value of the variable -`$disconnectAuthor` is `true`, if `false` or `null` are passed, it will not change. +The `author` relationship will only be disconnected if the value of the variable `$disconnectAuthor` is `true`, if `false` or `null` are passed, it will not change. ```json { @@ -253,9 +242,7 @@ mutation UpdatePost($disconnectAuthor: Boolean) { ## MorphTo -The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), -the main difference being that the `connect` operation requires an input type with both -the `id` and `type` of the related model. +The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), the main difference being that the `connect` operation requires an input type with both the `id` and `type` of the related model. ```graphql type Task { @@ -360,8 +347,7 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Phone` model. +This mutation takes a single argument `input` that contains values of the `User` itself and its associated `Phone` model. ```graphql input UpdateUserInput { @@ -427,8 +413,7 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Post` models. +This mutation takes a single argument `input` that contains values of the `User` itself and its associated `Post` models. ```graphql input CreateUserInput { @@ -437,8 +422,7 @@ input CreateUserInput { } ``` -Now, we can expose an operation that allows us to directly create new posts -right when we create the `User`. +Now, we can expose an operation that allows us to directly create new posts right when we create the `User`. ```graphql input CreatePostsHasMany { @@ -550,8 +534,7 @@ mutation { } ``` -The behaviour for `upsert` is a mix between updating and creating, -it will produce the needed action regardless of whether the model exists or not. +The behaviour for `upsert` is a mix between updating and creating, it will produce the needed action regardless of whether the model exists or not. ## MorphMany @@ -559,8 +542,7 @@ Works exactly like [Has Many](#hasmany). ## BelongsToMany -A belongs to many relation allows you to create new related models as well -as attaching existing ones. +A belongs to many relation allows you to create new related models as well as attaching existing ones. ```graphql type Mutation { @@ -589,8 +571,7 @@ input UpsertAuthorInput { } ``` -Just pass the ID of the models you want to associate or their full information -to create a new relation. +Just pass the ID of the models you want to associate or their full information to create a new relation. ```graphql mutation { @@ -638,8 +619,7 @@ Lighthouse will detect the relationship and attach, update or create it. } ``` -It is also possible to use the `sync` operation to ensure only the given IDs -will be contained withing the relation. +It is also possible to use the `sync` operation to ensure only the given IDs will be contained withing the relation. ```graphql mutation { @@ -670,8 +650,8 @@ input UpdateAuthorBelongsToMany { ### Storing Pivot Data It is common that many-to-many relations store some extra data in pivot tables. -Suppose we want to track what movies a user has seen. In addition to connecting -the two entities, we want to store how well they liked it: +Suppose we want to track what movies a user has seen. +In addition to connecting the two entities, we want to store how well they liked it: ```graphql type User { @@ -690,13 +670,11 @@ type UserMoviePivot { } ``` -Laravel's `sync()`, `syncWithoutDetaching()` or `connect()` methods allow you to pass -an array where the keys are IDs of related models and the values are pivot data. +Laravel's `sync()`, `syncWithoutDetaching()` or `connect()` methods allow you to pass an array where the keys are IDs of related models and the values are pivot data. Lighthouse exposes this capability through the nested operations on many-to-many relations. Instead of passing just a list of ids, you can define an `input` type that also contains pivot data. -It must contain a field called `id` to contain the ID of the related model, -all other fields will be inserted into the pivot table. +It must contain a field called `id` to contain the ID of the related model, all other fields will be inserted into the pivot table. ```graphql type Mutation { diff --git a/docs/4/eloquent/polymorphic-relationships.md b/docs/4/eloquent/polymorphic-relationships.md index bf6ead901d..bb132df7bd 100644 --- a/docs/4/eloquent/polymorphic-relationships.md +++ b/docs/4/eloquent/polymorphic-relationships.md @@ -27,8 +27,7 @@ type Image { ``` First, let's go ahead and add the relations to `Image` since they are straightforward. -The field name should match your relationship method name and be annotated -with the [@morphOne](../api-reference/directives.md#morphone) directive. +The field name should match your relationship method name and be annotated with the [@morphOne](../api-reference/directives.md#morphone) directive. ```graphql type Post { @@ -44,20 +43,17 @@ type User { } ``` -Depending on the rules of your application, you might require the relationship -to be there in some cases, while allowing it to be absent in others. In this -example, a `Post` must always have an `Image`, while a `User` does not require one. +Depending on the rules of your application, you might require the relationship to be there in some cases, while allowing it to be absent in others. +In this example, a `Post` must always have an `Image`, while a `User` does not require one. -For the inverse, you will need to define a [union type](../the-basics/types.md#union) -to express that an `Image` might be linked to different models. +For the inverse, you will need to define a [union type](../the-basics/types.md#union) to express that an `Image` might be linked to different models. ```graphql union Imageable = Post | User ``` Now, reference the union type from a field in your `Image` type. -You can use the [@morphTo](../api-reference/directives.md#morphto) directive -for performance optimization. +You can use the [@morphTo](../api-reference/directives.md#morphto) directive for performance optimization. ```graphql type Image { @@ -67,15 +63,13 @@ type Image { } ``` -The default type resolver will be able to determine which concrete object type is returned -when dealing with Eloquent models, so your definition should just work. +The default type resolver will be able to determine which concrete object type is returned when dealing with Eloquent models. +Your definition should just work. ## One to Many -Based on the above example, you could change your application to allow -for a `Post` to have many images attached to it. -The field `images` now returns a list of `Image` object and is annotated -with the [@morphMany](../api-reference/directives.md#morphmany) directive. +Based on the above example, you could change your application to allow for a `Post` to have many images attached to it. +The field `images` now returns a list of `Image` object and is annotated with the [@morphMany](../api-reference/directives.md#morphmany) directive. ```graphql type Post { diff --git a/docs/4/eloquent/relationships.md b/docs/4/eloquent/relationships.md index 91b967181a..418a87d890 100644 --- a/docs/4/eloquent/relationships.md +++ b/docs/4/eloquent/relationships.md @@ -36,19 +36,17 @@ type Post { } ``` -Because Laravel relationships can be accessed just like regular properties on your model, -the default field resolver will work just fine. +Because Laravel relationships can be accessed just like regular properties on your model, the default field resolver will work just fine. ## Avoiding the N+1 performance problem When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. -This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: -the so-called N+1 query problem. [Learn more](../performance/n-plus-one.md). +This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: the so-called N+1 query problem. +[Learn more](../performance/n-plus-one.md). -When you decorate your relationship fields with Lighthouse's built-in relationship -directives, queries are automatically combined through a technique called _batch loading_. +When you decorate your relationship fields with Lighthouse's built-in relationship directives, queries are automatically combined through a technique called _batch loading_. That means you get fewer database requests and better performance without doing much work. > Batch loading might not provide ideal performance for all use cases. You can turn @@ -56,8 +54,7 @@ That means you get fewer database requests and better performance without doing ## One To One -Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) -between two types in your schema. +Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) between two types in your schema. ```graphql type User { @@ -93,8 +90,7 @@ type Comment { ## Many To Many -While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) -are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. +While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. Use the [@belongsToMany](../api-reference/directives.md#belongstomany) directive to define it. ```graphql @@ -113,9 +109,8 @@ type Role { ## Renaming relations -When you define a relation, Lighthouse assumes that the field and the relationship -method have the same name. If you need to name your field differently, you have to -specify the name of the method. +When you define a relation, Lighthouse assumes that the field and the relationship method have the same name. +If you need to name your field differently, you have to specify the name of the method. ```graphql type Post { diff --git a/docs/4/eloquent/soft-deleting.md b/docs/4/eloquent/soft-deleting.md index ee4ba35b21..c5610e70b6 100644 --- a/docs/4/eloquent/soft-deleting.md +++ b/docs/4/eloquent/soft-deleting.md @@ -1,13 +1,10 @@ # Soft Deleting -Lighthouse offers convenient helpers to work with models that utilize -[soft deletes](https://laravel.com/docs/eloquent#soft-deleting). +Lighthouse offers convenient helpers to work with models that utilize [soft deletes](https://laravel.com/docs/eloquent#soft-deleting). ## Filter Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field -to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. ```graphql type Query { @@ -15,8 +12,7 @@ type Query { } ``` -Lighthouse will automatically add an argument `trashed` to the field definition -and include the enum `Trashed`. +Lighthouse will automatically add an argument `trashed` to the field definition and include the enum `Trashed`. ```graphql type Query { @@ -45,8 +41,7 @@ You can include soft deleted models in your result with a query like this: ## Restoring Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. ```graphql type Mutation { @@ -68,8 +63,7 @@ This mutation will return the restored object. ## Permanently Deleting Models -To truly remove a model from the database, -use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. +To truly remove a model from the database, use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. Your model must use the `Illuminate\Database\Eloquent\SoftDeletes` trait. ```graphql diff --git a/docs/4/getting-started/configuration.md b/docs/4/getting-started/configuration.md index 047c550bf2..aab6f5babb 100644 --- a/docs/4/getting-started/configuration.md +++ b/docs/4/getting-started/configuration.md @@ -11,9 +11,8 @@ The configuration file will be placed in `config/lighthouse.php`. ## CORS -A GraphQL API can be consumed from multiple clients, which may or may not reside -on the same domain as your server. Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) -for your GraphQL endpoint in `config/cors.php`: +A GraphQL API can be consumed from multiple clients, which may or may not reside on the same domain as your server. +Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) for your GraphQL endpoint in `config/cors.php`: ```diff return [ diff --git a/docs/4/getting-started/installation.md b/docs/4/getting-started/installation.md index 77af1ce139..ebef5b2469 100644 --- a/docs/4/getting-started/installation.md +++ b/docs/4/getting-started/installation.md @@ -10,8 +10,8 @@ composer require nuwave/lighthouse ## Publish the default schema -Lighthouse includes a default schema to get you going right away. Publish -it using the following `artisan` command: +Lighthouse includes a default schema to get you going right away. +Publish it using the following `artisan` command: ```bash php artisan vendor:publish --tag=lighthouse-schema @@ -26,21 +26,20 @@ $app->register(\Nuwave\Lighthouse\LighthouseServiceProvider::class); ``` The many features Lighthouse provides are split across multiple service providers. -Since Lumen does not support auto-discovery, you will have to register them individually -depending on which features you want to use. Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), -the section `extra.laravel.providers` contains the default service providers. +Since Lumen does not support auto-discovery, you will have to register them individually depending on which features you want to use. +Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), the section `extra.laravel.providers` contains the default service providers. ## IDE Support Lighthouse makes heavy use of the SDL and utilizes schema directives. -To improve your editing experience, you can generate a definition file -[with an artisan command](../api-reference/commands.md#ide-helper): +To improve your editing experience, you can generate a definition file [with an artisan command](../api-reference/commands.md#ide-helper): ```bash php artisan lighthouse:ide-helper ``` -This command requires `haydenpierce/class-finder`. Install it by running: +This command requires `haydenpierce/class-finder`. +Install it by running: ```bash composer require --dev haydenpierce/class-finder @@ -54,8 +53,7 @@ We recommend the following plugins: ## Install GraphQL DevTools -To make use of the amazing tooling around GraphQL, we recommend -installing [GraphQL Playground](https://github.com/mll-lab/laravel-graphql-playground). +To make use of the amazing tooling around GraphQL, we recommend installing [GraphQL Playground](https://github.com/mll-lab/laravel-graphql-playground). ```bash composer require mll-lab/laravel-graphql-playground @@ -63,5 +61,5 @@ composer require mll-lab/laravel-graphql-playground After installation, visit `/graphql-playground` to try it. -You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in -the config. By default, the endpoint lives at `/graphql`. +You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in the config. +By default, the endpoint lives at `/graphql`. diff --git a/docs/4/getting-started/migrating-to-lighthouse.md b/docs/4/getting-started/migrating-to-lighthouse.md index f1e0514e0d..531660db6a 100644 --- a/docs/4/getting-started/migrating-to-lighthouse.md +++ b/docs/4/getting-started/migrating-to-lighthouse.md @@ -1,15 +1,12 @@ # Migrating to Lighthouse -This section contains advice on how you can migrate existing -API projects to Lighthouse. +This section contains advice on how you can migrate existing API projects to Lighthouse. ## Schema definition -The most important thing to get you started using Lighthouse will -be a schema that is written using GraphQL Schema Definition Language. +The most important thing to get you started using Lighthouse will be a schema that is written using GraphQL Schema Definition Language. -If you already have a server with another library up and running, you -can use introspection to retrieve this schema and save it to a file. +If you already have a server with another library up and running, you can use introspection to retrieve this schema and save it to a file. A simple tool that is also generally useful is [graphql-cli](https://github.com/graphql-cli/graphql-cli). @@ -17,23 +14,18 @@ A simple tool that is also generally useful is [graphql-cli](https://github.com/ graphql init graphql get-schema --endpoint=example.com/graphql --output=schema.graphql -Type definitions that previously done through code can mostly be deduced from -the schema. Sometimes, additional annotations or a PHP implementation is required. +Type definitions that previously done through code can mostly be deduced from the schema. +Sometimes, additional annotations or a PHP implementation is required. [How to define types](../the-basics/types.md) ## Resolver logic -If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), -[rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that -is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), -you should be able to reuse much of your existing code. +If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), [rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), you should be able to reuse much of your existing code. -You can also register your existing types within Lighthouse's type registry, so you -won't have to rewrite them in SDL: [Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). +You can also register your existing types within Lighthouse's type registry, so you won't have to rewrite them in SDL. +[Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). -Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature), -so you should be able to reuse any logic you have written for Queries/Mutations. +Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature). +You should be able to reuse any logic you have written for Queries/Mutations. -Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), -[eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), -[pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). +Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), [eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), [pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). diff --git a/docs/4/performance/deferred.md b/docs/4/performance/deferred.md index 2e6ea0a723..b2db66a30d 100644 --- a/docs/4/performance/deferred.md +++ b/docs/4/performance/deferred.md @@ -1,12 +1,10 @@ # Deferred Fields -::: warning -Currently the `@defer` directive requires Apollo Client in alpha. -Track the state of the PR here: https://github.com/apollographql/apollo-client/pull/3686#issuecomment-555534519 -::: +::: warning Currently the `@defer` directive requires Apollo Client in alpha. +Track the state of the PR here: https://github.com/apollographql/apollo-client/pull/3686#issuecomment-555534519 ::: -Deferring fields allows you to prioritize fetching data needed to render the most important content -as fast as possible, and then loading the rest of the page in the background. +Deferring fields allows you to prioritize fetching data needed to render the most important content as fast as possible, +and then loading the rest of the page in the background. Lighthouse adds support for the experimental `@defer` directive through an extension. Read more about it [here](https://www.apollographql.com/blog/introducing-defer-in-apollo-server-f6797c4e9d6e). @@ -23,10 +21,8 @@ Add the service provider to your `config/app.php`: ## Configuration -Consider the configuration options in your `config/lighthouse.php` to prevent -deferred queries from running to long. +Consider the configuration options in your `config/lighthouse.php` to prevent deferred queries from running to long.
-![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) -_(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ +![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) _(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ diff --git a/docs/4/performance/n-plus-one.md b/docs/4/performance/n-plus-one.md index 0584ccceb5..5a3aed9df2 100644 --- a/docs/4/performance/n-plus-one.md +++ b/docs/4/performance/n-plus-one.md @@ -1,10 +1,8 @@ # The N+1 Query Problem -A common performance pitfall that comes with the nested nature of GraphQL queries -is the so-called N+1 query problem. +A common performance pitfall that comes with the nested nature of GraphQL queries is the so-called N+1 query problem. -Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the -name of the associated author: +Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the name of the associated author: ```graphql { @@ -17,18 +15,14 @@ name of the associated author: } ``` -Following a naive execution strategy, Lighthouse would first query a list of posts, -then loop over that list and resolve the individual fields. -The associated author for each post would be lazily loaded, querying the database -once per post. +Following a naive execution strategy, Lighthouse would first query a list of posts, then loop over that list and resolve the individual fields. +The associated author for each post would be lazily loaded, querying the database once per post. ## Eager Loading Relationships -When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) -is commonly used to alleviate the N+1 query problem. +When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) is commonly used to alleviate the N+1 query problem. -You can leverage eager loading by informing Lighthouse of the relationships between your models, -using directives such as [@belongsTo](../api-reference/directives.md#belongsto) and [@hasMany](../api-reference/directives.md#hasmany). +You can leverage eager loading by informing Lighthouse of the relationships between your models, using directives such as [@belongsTo](../api-reference/directives.md#belongsto) and [@hasMany](../api-reference/directives.md#hasmany). ```graphql type Post { @@ -44,12 +38,11 @@ type User { Under the hood, Lighthouse will batch the relationship queries together in a single database query. -If you require a relation to be loaded for some field, but do not wish to return the relationship itself, -you can use the [@with](../api-reference/directives.md#with) directive. +If you require a relation to be loaded for some field. +Do not wish to return the relationship itself, you can use the [@with](../api-reference/directives.md#with) directive. ## Data Loader -`webonyx/graphql-php` allows deferring the actual resolution of a field until it is actually needed, -read more [in their documentation](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). +`webonyx/graphql-php` allows deferring the actual resolution of a field until it is actually needed, read more [in their documentation](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). You can extend `\Nuwave\Lighthouse\Execution\DataLoader\BatchLoader` if you require custom batch loading. diff --git a/docs/4/performance/schema-caching.md b/docs/4/performance/schema-caching.md index 54d3144bfb..f7b06543db 100644 --- a/docs/4/performance/schema-caching.md +++ b/docs/4/performance/schema-caching.md @@ -1,7 +1,6 @@ # Schema caching -As your schema grows larger, the construction of the schema from raw `.graphql` files -becomes more and more costly. +As your schema grows larger, the construction of the schema from raw `.graphql` files becomes more and more costly. Make sure to enable schema caching when shipping Lighthouse to production. diff --git a/docs/4/performance/server-configuration.md b/docs/4/performance/server-configuration.md index 9339ebf235..561c14b335 100644 --- a/docs/4/performance/server-configuration.md +++ b/docs/4/performance/server-configuration.md @@ -9,5 +9,4 @@ If you have the freedom to install it on your server, it's an easy way to get a ## Xdebug -Enabling Xdebug and having an active debug session slows down execution by -an order of magnitude. +Enabling Xdebug and having an active debug session slows down execution by an order of magnitude. diff --git a/docs/4/security/authentication.md b/docs/4/security/authentication.md index c589d2a093..6070d2e926 100644 --- a/docs/4/security/authentication.md +++ b/docs/4/security/authentication.md @@ -1,16 +1,13 @@ # Authentication -You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) -to authenticate users of your GraphQL API. +You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) to authenticate users of your GraphQL API. ## AttemptAuthentication middleware -As all GraphQL requests are served at a single HTTP endpoint, middleware added -through the `lighthouse.php` config will run for all queries against your server. +As all GraphQL requests are served at a single HTTP endpoint, middleware added through the `lighthouse.php` config will run for all queries against your server. -In most cases, your schema will have some publicly accessible fields and others -that require authentication. As multiple checks for authentication or permissions may be -required in a single request, it is convenient to attempt authentication once per request. +In most cases, your schema will have some publicly accessible fields and others that require authentication. +As multiple checks for authentication or permissions may be required in a single request, it is convenient to attempt authentication once per request. ```php 'route' => [ @@ -20,12 +17,10 @@ required in a single request, it is convenient to attempt authentication once pe ], ``` -Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated -access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. +Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. -If you want to guard all your fields against unauthenticated access, you can simply add -Laravel's build-in auth middleware. Beware that this approach does not allow any GraphQL -operations for guest users, so you will have to handle login outside of GraphQL. +If you want to guard all your fields against unauthenticated access, you can simply add Laravel's build-in auth middleware. +Beware that this approach does not allow any GraphQL operations for guest users, so you will have to handle login outside of GraphQL. ```php 'middleware' => [ @@ -41,15 +36,13 @@ You can configure a default guard to use for authenticating GraphQL requests in 'guard' => 'api', ``` -This setting is used whenever Lighthouse looks for an authenticated user, for example in directives -such as [@guard](../api-reference/directives.md#guard), or when applying the `AttemptAuthentication` middleware. +This setting is used whenever Lighthouse looks for an authenticated user, for example in directives such as [@guard](../api-reference/directives.md#guard), or when applying the `AttemptAuthentication` middleware. Stateless guards are recommended for most use cases, such as the default `api` guard. ### Laravel Sanctum -If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard -to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as first middleware for Lighthouse's route. +If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as first middleware for Lighthouse's route. ```php 'route' => [ @@ -63,16 +56,13 @@ to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as first 'guard' => 'sanctum', ``` -Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) -with all GraphQL requests, regardless of whether the user is authenticated or not. +Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) with all GraphQL requests, regardless of whether the user is authenticated or not. -When using [laravel-graphql-playground](https://github.com/mll-lab/laravel-graphql-playground), follow the [instructions -to add a CSRF token](https://github.com/mll-lab/laravel-graphql-playground#configure-session-authentication). +When using [laravel-graphql-playground](https://github.com/mll-lab/laravel-graphql-playground), follow the [instructions to add a CSRF token](https://github.com/mll-lab/laravel-graphql-playground#configure-session-authentication). ## Guard selected fields -If you want to guard only selected fields, you can use the [@guard](../api-reference/directives.md#guard) -directive to require authentication for accessing them. +If you want to guard only selected fields, you can use the [@guard](../api-reference/directives.md#guard) directive to require authentication for accessing them. ```graphql type Query { @@ -80,8 +70,8 @@ type Query { } ``` -If you need to guard multiple fields, just use [@guard](../api-reference/directives.md#guard) -on a `type` or an `extend type` definition. It will be applied to all fields within that type. +If you need to guard multiple fields, just use [@guard](../api-reference/directives.md#guard) on a `type` or an `extend type` definition. +It will be applied to all fields within that type. ```graphql extend type Query @guard @@ -101,8 +91,7 @@ type Query { } ``` -Sending the following query will return the authenticated user's info -or `null` if the request is not authenticated. +Sending the following query will return the authenticated user's info or `null` if the request is not authenticated. ```graphql { @@ -115,9 +104,7 @@ or `null` if the request is not authenticated. ## Stateful Authentication Example -You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). -**This only works when Lighthouse's guard uses a session driver.** -Laravel's token based authentication does not allow logging in or out on the server side. +You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). **This only works when Lighthouse's guard uses a session driver.** Laravel's token based authentication does not allow logging in or out on the server side. The implementation in the docs is only an example and may have to be adapted to your specific use case. diff --git a/docs/4/security/authorization.md b/docs/4/security/authorization.md index d404d6f88e..b45faff609 100644 --- a/docs/4/security/authorization.md +++ b/docs/4/security/authorization.md @@ -3,8 +3,7 @@ Not every user in your application may be allowed to see all data or do any action. You can control what they can do by enforcing authorization rules. -Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's -a prerequisite to have your users logged in before checking what they can do. +Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's a prerequisite to have your users logged in before checking what they can do. ## Utilize the Viewer pattern @@ -39,8 +38,7 @@ type Note { } ``` -Now, authenticated users can query for items that belong to them and are naturally -limited to seeing just those. +Now, authenticated users can query for items that belong to them and are naturally limited to seeing just those. ```graphql { @@ -57,8 +55,7 @@ limited to seeing just those. ## Restrict fields through policies Lighthouse allows you to restrict field operations to a certain group of users. -Use the [@can](../api-reference/directives.md#can) directive -to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. +Use the [@can](../api-reference/directives.md#can) directive to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. Starting from Laravel 5.7, [authorization of guest users](https://laravel.com/docs/authorization#guest-users) is supported. Because of this, Lighthouse does **not** validate that the user is authenticated before passing it along to the policy. @@ -89,9 +86,8 @@ class PostPolicy ### Protect specific model instances For some models, you may want to restrict access for specific instances of a model. -Use the `find` parameter to specify the name of an input argument that is the primary -key of the model. Lighthouse will use that to find a specific model -instance against which the permissions should be checked: +Use the `find` parameter to specify the name of an input argument that is the primary key of the model. +Lighthouse will use that to find a specific model instance against which the permissions should be checked: ```graphql type Query { @@ -110,8 +106,7 @@ class PostPolicy ``` Finding models combines nicely with [soft deleting](../eloquent/soft-deleting.md). -Lighthouse will detect if the query will require a filter for trashed models and -apply that as needed. +Lighthouse will detect if the query will require a filter for trashed models and apply that as needed. ### Passing additional arguments @@ -134,8 +129,7 @@ class PostPolicy } ``` -You can pass along the client given input data as arguments to the policy checks -with the `injectArgs` argument: +You can pass along the client given input data as arguments to the policy checks with the `injectArgs` argument: ```graphql type Mutation { @@ -153,8 +147,7 @@ class PostPolicy } ``` -When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as -the second parameter and the static `args` as the third parameter: +When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as the second parameter and the static `args` as the third parameter: ```php class PostPolicy @@ -165,15 +158,12 @@ class PostPolicy ## Custom field restrictions -For applications with role management, it is common to hide some model attributes from a -certain group of users. At the moment, Laravel and Lighthouse offer no canonical solution -for this. +For applications with role management, it is common to hide some model attributes from a certain group of users. +At the moment, Laravel and Lighthouse offer no canonical solution for this. -A great way to implement something that fits your use case is to create -[a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). +A great way to implement something that fits your use case is to create [a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). Field middleware allows you to intercept field access and conditionally hide them. -You can hide a field by returning `null` instead of calling the final resolver, or maybe even -abort execution by throwing an error. +You can hide a field by returning `null` instead of calling the final resolver, or maybe even abort execution by throwing an error. The following directive `@canAccess` is an example implementation, make sure to adapt it to your needs. It assumes a simple role system where a `User` has a single attribute `$role`. diff --git a/docs/4/security/resource-exhaustion.md b/docs/4/security/resource-exhaustion.md index 27fdc82848..168d7e8eb2 100644 --- a/docs/4/security/resource-exhaustion.md +++ b/docs/4/security/resource-exhaustion.md @@ -1,10 +1,10 @@ # Preventing Resource Exhaustion -GraphQL gives enormous power to clients. But with great power come great responsibilities đŸ•·. +GraphQL gives enormous power to clients. +But with great power come great responsibilities đŸ•·. -Since clients have the possibility to craft very complex queries, our servers must be ready -to handle them properly. These queries may be abusive queries from evil clients, -or may simply be very large queries used by legitimate clients. +Since clients have the possibility to craft very complex queries, our servers must be ready to handle them properly. +These queries may be abusive queries from evil clients, or may simply be very large queries used by legitimate clients. In both of these cases, the client can potentially take your GraphQL server down. _This intro was taken from HowToGraphQL, we recommend reading their full chapter on security https://www.howtographql.com/advanced/4-security/_ diff --git a/docs/4/security/sanitization.md b/docs/4/security/sanitization.md index 0b0b0a765b..92bb6a9adf 100644 --- a/docs/4/security/sanitization.md +++ b/docs/4/security/sanitization.md @@ -1,16 +1,14 @@ # Sanitization When dealing with user input, you need to make sure the given data is valid. -While [validation](validation) is a great first line of defense, there are cases where -it is most practical to modify the given input to ensure it is valid or safe to use. +While [validation](validation) is a great first line of defense, there are cases where it is most practical to modify the given input to ensure it is valid or safe to use. ## Single arguments A great way to deal with single values is to use an [`ArgTransformerDirective`](../custom-directives/argument-directives.md#argtransformerdirective). Lighthouse offers a few built-in options, but it is also really easy to build your own. -Here is how you can remove whitespace of a given input string by using -the built-in [@trim](../api-reference/directives.md#trim) directive: +Here is how you can remove whitespace of a given input string by using the built-in [@trim](../api-reference/directives.md#trim) directive: ```graphql type Mutation { @@ -20,6 +18,4 @@ type Mutation { ## Complex arguments -When you need to look at multiple input fields in order to run sanitization, you can use -a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) -to transform the given inputs before passing them along to the final resolver. +When you need to look at multiple input fields in order to run sanitization, you can use a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) to transform the given inputs before passing them along to the final resolver. diff --git a/docs/4/security/validation.md b/docs/4/security/validation.md index a65bacf568..4874dd9a60 100644 --- a/docs/4/security/validation.md +++ b/docs/4/security/validation.md @@ -1,12 +1,10 @@ # Validation -Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) for your -queries and mutations. +Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) for your queries and mutations. ## Single Arguments -The simplest way to leverage the built-in validation rules is to use the -[@rules](../api-reference/directives.md#rules) directive. +The simplest way to leverage the built-in validation rules is to use the [@rules](../api-reference/directives.md#rules) directive. ```graphql type Mutation { @@ -14,8 +12,7 @@ type Mutation { } ``` -In the case of a validation error, Lighthouse will abort execution and return the validation messages -as part of the response. +In the case of a validation error, Lighthouse will abort execution and return the validation messages as part of the response. ```graphql mutation { @@ -76,11 +73,9 @@ input CreatePostInput { } ``` -Using the [`unique`](https://laravel.com/docs/validation#rule-unique) -validation rule can be a bit tricky. +Using the [`unique`](https://laravel.com/docs/validation#rule-unique) validation rule can be a bit tricky. -If the argument is nested within an input object, the argument path will not -match the column name, so you have to specify the column name explicitly. +If the argument is nested within an input object, the argument path will not match the column name, so you have to specify the column name explicitly. ```graphql input CreateUserInput { @@ -90,8 +85,7 @@ input CreateUserInput { ## Validating Arrays -When you are passing in an array as an argument to a field, you might -want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) +When you are passing in an array as an argument to a field, you might want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) ```graphql type Mutation { @@ -102,8 +96,7 @@ type Mutation { } ``` -You can also combine this with [@rules](../api-reference/directives.md#rules) to validate -both the size and the contents of an argument array. +You can also combine this with [@rules](../api-reference/directives.md#rules) to validate both the size and the contents of an argument array. For example, you might require a list of at least 3 valid emails to be passed. ```graphql @@ -116,12 +109,11 @@ type Mutation { ## Validate Fields -In some cases, validation rules are more complex and need to use entirely custom logic -or take multiple arguments into account. +In some cases, validation rules are more complex and need to use entirely custom logic or take multiple arguments into account. -To create a reusable validator that can be applied to fields, extend the base validation -directive `\Nuwave\Lighthouse\Schema\Directives\ValidationDirective`. Your custom directive -class should be located in one of the configured default directive namespaces, e.g. `App\GraphQL\Directives`. +To create a reusable validator that can be applied to fields, extend the base validation directive `\Nuwave\Lighthouse\Schema\Directives\ValidationDirective`. +Your custom directive class should be located in one of the configured default directive namespaces, e.g. +`App\GraphQL\Directives`. ```php title = $newTitle; diff --git a/docs/4/testing/extensions.md b/docs/4/testing/extensions.md index bfde857d64..da115bf22f 100644 --- a/docs/4/testing/extensions.md +++ b/docs/4/testing/extensions.md @@ -1,12 +1,10 @@ # Testing Lighthouse extensions -When you extend Lighthouse with custom functionality, it is a great idea to test -your extensions in isolation from the rest of your application. +When you extend Lighthouse with custom functionality, it is a great idea to test your extensions in isolation from the rest of your application. ## Use a test schema -When you enhance functionality related to the schema definition, such as adding -a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. +When you enhance functionality related to the schema definition, such as adding a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. Add the `UsesTestSchema` trait to your test class, call `setUpTestSchema()` and define your test schema: ```php @@ -50,8 +48,8 @@ class MyCustomDirectiveTest extends TestCase ## Mock resolvers -When testing custom functionality through a dummy schema, you still need to have -a way to resolve fields. Lighthouse provides a simple way to mock resolvers in a dummy schema. +When testing custom functionality through a dummy schema, you still need to have a way to resolve fields. +Lighthouse provides a simple way to mock resolvers in a dummy schema. Add the `MocksResolvers` trait to your test class: @@ -102,9 +100,9 @@ public function testReverseField(): void } ``` -Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert -that our resolver is called with certain values. Note that we are not passing an -explicit resolver function here. The default resolver will simply return `null`. +Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert that our resolver is called with certain values. +Note that we are not passing an explicit resolver function here. +The default resolver will simply return `null`. ```php public function testReverseInput(): void @@ -130,8 +128,7 @@ public function testReverseInput(): void } ``` -If you have to handle the incoming resolver arguments dynamically, you can also -pass a function that is called: +If you have to handle the incoming resolver arguments dynamically, you can also pass a function that is called: ```php public function testReverseInput(): void @@ -158,8 +155,8 @@ public function testReverseInput(): void } ``` -You might have a need to add multiple resolvers to a single schema. For that case, -specify a unique `key` for the mock resolver (it defaults to `default`): +You might have a need to add multiple resolvers to a single schema. +For that case, specify a unique `key` for the mock resolver (it defaults to `default`): ```php public function testMultipleResolvers(): void diff --git a/docs/4/testing/phpunit.md b/docs/4/testing/phpunit.md index 74ffaf6a79..1102408f92 100644 --- a/docs/4/testing/phpunit.md +++ b/docs/4/testing/phpunit.md @@ -4,8 +4,8 @@ Lighthouse makes it easy to add automated tests through PHPUnit. ## Setup -Lighthouse offers some useful test helpers that make it easy to call your API -from within a PHPUnit test. Just add the `MakesGraphQLRequests` trait to your test class. +Lighthouse offers some useful test helpers that make it easy to call your API from within a PHPUnit test. +Just add the `MakesGraphQLRequests` trait to your test class. ```diff multipartGraphQL( @@ -187,8 +185,8 @@ $this->multipartGraphQL( ## Introspection -If you create or manipulate parts of your schema programmatically, you might -want to test that. You can use introspection to query your final schema in tests. +If you create or manipulate parts of your schema programmatically, you might want to test that. +You can use introspection to query your final schema in tests. Lighthouse uses the introspection query from [`\GraphQL\Type\Introspection::getIntrospectionQuery()`](https://github.com/webonyx/graphql-php/blob/master/src/Type/Introspection.php). @@ -254,8 +252,7 @@ $this->setUpDeferStream(); ## Lumen -Because the `TestResponse` class is not available in Lumen, you must use a different -test trait: +Because the `TestResponse` class is not available in Lumen, you must use a different test trait: ```diff ` -and including it in your schema. Lighthouse will look for Scalar types in a configurable -default namespace. +Define your own scalar types by running `php artisan lighthouse:scalar ` and including it in your schema. +Lighthouse will look for Scalar types in a configurable default namespace. ```graphql scalar ZipCode @@ -85,8 +83,8 @@ type Query { } ``` -In this example, the underlying values are actually integers. When the models are retrieved from -the database, the mapping is applied and the integers are converted to the defined string keys. +In this example, the underlying values are actually integers. +When the models are retrieved from the database, the mapping is applied and the integers are converted to the defined string keys. ```php return [ @@ -131,11 +129,9 @@ The PHP internal value of the field `ADMIN` will be `string('ADMIN')`. ### Native PHP definition -If you want to reuse enum definitions or constants from PHP, you can also -register a native PHP enum type [through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types). +If you want to reuse enum definitions or constants from PHP, you can also register a native PHP enum type [through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types). -Just define a [EnumType](https://webonyx.github.io/graphql-php/type-definitions/enums) and -register it: +Just define a [EnumType](https://webonyx.github.io/graphql-php/type-definitions/enums) and register it: ```php use GraphQL\Type\Definition\EnumType; @@ -166,8 +162,7 @@ $typeRegistry = app(TypeRegistry::class); $typeRegistry->register($episodeEnum); ``` -If you are using [BenSampo/laravel-enum](https://github.com/BenSampo/laravel-enum) -you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. +If you are using [BenSampo/laravel-enum](https://github.com/BenSampo/laravel-enum) you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. Given the following enum: @@ -187,8 +182,8 @@ final class UserType extends Enum } ``` -This is how you can register it in a ServiceProvider. Make sure to wrap it -in a `LaravelEnumType`. +This is how you can register it in a ServiceProvider. +Make sure to wrap it in a `LaravelEnumType`. ```php name; // UserKind ## Input Input types can be used to describe complex objects for field arguments. -Beware that while they look similar to Object Types, they behave differently: -The fields of an Input Type are treated similar to arguments. +Beware that while they look similar to Object Types, they behave differently: The fields of an Input Type are treated similar to arguments. ```graphql input CreateUserInput { @@ -283,21 +277,19 @@ type User implements Named { } ``` -Interfaces need a way of determining which concrete Object Type is returned by a -particular query. Lighthouse provides a default type resolver that works by calling -`class_basename($value)` on the value returned by the resolver. +Interfaces need a way of determining which concrete Object Type is returned by a particular query. +Lighthouse provides a default type resolver that works by calling `class_basename($value)` on the value returned by the resolver. -You can also provide a custom type resolver. Run `php artisan lighthouse:interface ` to create -a custom interface class. It is automatically put in the default namespace where Lighthouse can discover it by itself. +You can also provide a custom type resolver. +Run `php artisan lighthouse:interface ` to create a custom interface class. +It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) ## Union A Union is an abstract type that simply enumerates other Object Types. -They are similar to interfaces in that they can return different types, but they can not -have fields defined. +They are similar to interfaces in that they can return different types, but they can not have fields defined. ```graphql union Person = User | Employee @@ -311,10 +303,8 @@ type Employee { } ``` -Just like Interfaces, you need a way to determine the concrete Object Type for a Union, -based on the resolved value. If the default type resolver does not work for you, define your -own using `php artisan lighthouse:union `. +Just like Interfaces, you need a way to determine the concrete Object Type for a Union, based on the resolved value. +If the default type resolver does not work for you, define your own using `php artisan lighthouse:union `. It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) diff --git a/docs/5/api-reference/commands.md b/docs/5/api-reference/commands.md index 2f0096d27e..38590c2dc9 100644 --- a/docs/5/api-reference/commands.md +++ b/docs/5/api-reference/commands.md @@ -1,7 +1,7 @@ # Artisan Commands -Lighthouse provides some convenient artisan commands. All of them -are namespaced under `lighthouse`. +Lighthouse provides some convenient artisan commands. +All of them are namespaced under `lighthouse`. ## cache @@ -35,8 +35,7 @@ This will create the following files: - `programmatic-types.graphql`: Schema definitions for programmatically registered types, if you have any - `_lighthouse_ide_helper.php`: Class definitions for some magical PHP, such as the `TestResponse` mixin -A great way to keep up to date with your current version of Lighthouse -is to add this script to your `composer.json`: +A great way to keep up to date with your current version of Lighthouse is to add this script to your `composer.json`: ```json "scripts": { @@ -66,12 +65,10 @@ Compile the GraphQL schema and print the result. php artisan lighthouse:print-schema -This can be quite useful, as the root `.graphql` files do not necessarily -contains the whole schema. Schema imports, native PHP types and schema manipulation -may influence the final schema. +This can be quite useful, as the root `.graphql` files do not necessarily contains the whole schema. +Schema imports, native PHP types and schema manipulation may influence the final schema. -Use the `-W` / `--write` option to output the schema to the default file storage -(usually `storage/app`) as `lighthouse-schema.graphql`. +Use the `-W` / `--write` option to output the schema to the default file storage (usually `storage/app`) as `lighthouse-schema.graphql`. You can output your schema in JSON format by using the `--json` flag. diff --git a/docs/5/api-reference/directives.md b/docs/5/api-reference/directives.md index d0d725a2cb..725331d2a1 100644 --- a/docs/5/api-reference/directives.md +++ b/docs/5/api-reference/directives.md @@ -133,8 +133,8 @@ directive @all( ) on FIELD_DEFINITION ``` -This assumes your model has the same name as the type you are returning and is defined -in the default model namespace `App`. [You can change this configuration](../getting-started/configuration.md). +This assumes your model has the same name as the type you are returning and is defined in the default model namespace `App`. +[You can change this configuration](../getting-started/configuration.md). ```graphql type Query { @@ -171,8 +171,7 @@ type Query { } ``` -If you need to use a guard besides the default to resolve the authenticated user, -you can pass the guard name as the `guard` argument +If you need to use a guard besides the default to resolve the authenticated user, you can pass the guard name as the `guard` argument ```graphql type Query { @@ -223,8 +222,7 @@ class Post extends Model } ``` -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type Post { @@ -323,8 +321,7 @@ class User extends Model ### Rename Relation -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument if your relationship method has a different name than the field. ```graphql type User { @@ -334,16 +331,13 @@ type User { ### Retrieving Intermediate Table Columns -You may want to allow accessing data that describes the relation between the models -and is stored in the intermediate table - see [retrieving intermediate table columns in Laravel](https://laravel.com/docs/eloquent-relationships#retrieving-intermediate-table-columns). +You may want to allow accessing data that describes the relation between the models and is stored in the intermediate table - see [retrieving intermediate table columns in Laravel](https://laravel.com/docs/eloquent-relationships#retrieving-intermediate-table-columns). Just like in Laravel, you can access the `pivot` attribute on the models (or its alias). -Even though this attribute is always present when querying the model through the relation, -it may not be present when reaching the node through another path in the schema, so it is -recommended to define the field as nullable (no `!`). +Even though this attribute is always present when querying the model through the relation, it may not be present when reaching the node through another path in the schema. +It is recommended to define the field as nullable (no `!`). -The following example assumes the intermediate table between `User` and `Role` defines -a column `meta`. +The following example assumes the intermediate table between `User` and `Role` defines a column `meta`. ```php use Illuminate\Database\Eloquent\Model; @@ -386,8 +380,7 @@ type RoleUserPivot { } ``` -When using the `type` argument with pagination style `CONNECTION`, you may create your own [edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) -that contains the attributes of the intermediate table. +When using the `type` argument with pagination style `CONNECTION`, you may create your own [edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) that contains the attributes of the intermediate table. The custom edge type must contain at least the following two fields: @@ -440,8 +433,7 @@ type Mutation { } ``` -You may override the default queueing behaviour from the configuration by -passing the `shouldQueue` argument. +You may override the default queueing behaviour from the configuration by passing the `shouldQueue` argument. ```graphql type Mutation { @@ -477,15 +469,13 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar BuilderValue ``` -You must point to a `method` which will receive the builder instance -and can apply additional constraints to the query. +You must point to a `method` which will receive the builder instance and can apply additional constraints to the query. > This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). When used on an argument, the value is supplied as the second parameter to the method. -When used on a field, the value argument inside the directive is applied as the second -parameter to the method. +When used on a field, the value argument inside the directive is applied as the second parameter to the method. ```graphql type Query { @@ -661,8 +651,7 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar CanArgs ``` -The name of the returned Type `Post` is used as the Model class, however you may overwrite this by -passing the `model` argument: +The name of the returned Type `Post` is used as the Model class, however you may overwrite this by passing the `model` argument: ```graphql type Mutation { @@ -759,8 +748,7 @@ type Query { } ``` -A custom complexity function may look like the following, -refer to the [complexity function signature](resolvers.md#complexity-function-signature). +A custom complexity function may look like the following, refer to the [complexity function signature](resolvers.md#complexity-function-signature). ```php namespace App\Security; @@ -802,8 +790,7 @@ type Mutation { } ``` -Non-nullable arguments will _not_ be converted when this directive is used on a field, -but will be converted when it is used directly on the argument. +Non-nullable arguments will _not_ be converted when this directive is used on a field, but will be converted when it is used directly on the argument. ```graphql type Mutation { @@ -814,8 +801,7 @@ type Mutation { } ``` -If you want this for all your fields, consider adding this directive to your -global field middleware in `lighthouse.php`: +If you want this for all your fields, consider adding this directive to your global field middleware in `lighthouse.php`: ```php 'field_middleware' => [ @@ -908,8 +894,7 @@ type Mutation { } ``` -If you are using a single input object as an argument, you must tell Lighthouse -to spread out the nested values before applying it to the resolver. +If you are using a single input object as an argument, you must tell Lighthouse to spread out the nested values before applying it to the resolver. ```graphql type Mutation { @@ -921,8 +906,7 @@ input CreatePostInput { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, or is located in a non-default namespace, set it with the `model` argument. ```graphql type Mutation { @@ -971,8 +955,8 @@ type Mutation { } ``` -In the upcoming `v6`, the `@delete`, `@forceDelete` and `@restore` directives no longer offer the -`globalId` argument. Use `@globalId` on the argument instead. +In the upcoming `v6`, the `@delete`, `@forceDelete` and `@restore` directives no longer offer the `globalId` argument. +Use `@globalId` on the argument instead. ```diff type Mutation { @@ -982,8 +966,7 @@ type Mutation { ``` You can also delete multiple models at once. -Define a field that takes a list of IDs and returns a collection of the -deleted models. +Define a field that takes a list of IDs and returns a collection of the deleted models. _In contrast to Laravel mass updates, this does trigger model events._ @@ -993,8 +976,7 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, or is located in a non-default namespace, set it with the `model` argument. ```graphql type Mutation { @@ -1011,9 +993,7 @@ type Mutation { } ``` -If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or -`MorphTo` relationship, you can just pass a Boolean instead of an ID, as there is only one -possible model that can be deleted. +If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or `MorphTo` relationship, you can just pass a Boolean instead of an ID, as there is only one possible model that can be deleted. ```graphql type Mutation { @@ -1039,8 +1019,7 @@ directive @deprecated( ``` You can mark fields as deprecated by adding the [@deprecated](#deprecated) directive. -It is recommended to provide a `reason` for the deprecation, as well as a suggestion on -how to move forward. +It is recommended to provide a `reason` for the deprecation, as well as a suggestion on how to move forward. ```graphql type Query { @@ -1049,8 +1028,7 @@ type Query { } ``` -Deprecated elements are not included in introspection queries by default, -but they can still be queried by clients. +Deprecated elements are not included in introspection queries by default, but they can still be queried by clients. ## @drop @@ -1061,8 +1039,7 @@ Ignore the user given value, don't pass it to the resolver. directive @drop on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -This is useful when you want to deprecate a field, but avoid breaking changes -for clients that still pass the value. +This is useful when you want to deprecate a field, but avoid breaking changes for clients that still pass the value. ```graphql type User { @@ -1106,9 +1083,8 @@ type Mutation { } ``` -If your field is defined on the root types `Query` or `Mutation`, you can take advantage -of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). The following -will look for a class in `App\GraphQL\Queries` by default. +If your field is defined on the root types `Query` or `Mutation`, you can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md). +The following will look for a class in `App\GraphQL\Queries` by default. ```graphql type Query { @@ -1116,8 +1092,8 @@ type Query { } ``` -Be aware that resolvers are not limited to root fields. A resolver can be used for basic tasks -such as transforming the value of scalar fields, e.g. reformat a date. +Be aware that resolvers are not limited to root fields. +A resolver can be used for basic tasks such as transforming the value of scalar fields, e.g. reformat a date. ```graphql type User { @@ -1262,8 +1238,8 @@ enum Role { } ``` -You do not need this directive if the internal value of each enum key -is an identical string. [Read more about enum types](../the-basics/types.md#enum) +You do not need this directive if the internal value of each enum key is an identical string. +[Read more about enum types](../the-basics/types.md#enum) ## @eq @@ -1302,8 +1278,7 @@ type User { } ``` -If the name of the argument does not match the database column, -pass the actual column name as the `key`. +If the name of the argument does not match the database column, pass the actual column name as the `key`. ```graphql type User { @@ -1392,8 +1367,7 @@ enum GlobalIdDecode { } ``` -Instead of the original ID, the `id` field will now return a base64-encoded String -that globally identifies the User and can be used for querying the `node` endpoint. +Instead of the original ID, the `id` field will now return a base64-encoded String that globally identifies the User and can be used for querying the `node` endpoint. ```graphql type User { @@ -1402,8 +1376,7 @@ type User { } ``` -The field resolver will receive the decoded version of the passed `id`, -split into type and ID. +The field resolver will receive the decoded version of the passed `id`, split into type and ID. ```graphql type Mutation { @@ -1411,8 +1384,7 @@ type Mutation { } ``` -You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global ids. +You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global ids. ## @guard @@ -1447,15 +1419,13 @@ To ensure the user is logged in, add the `AttemptAuthenticate` middleware to you ], ``` -A useful pattern is to group fields in an `extend type` to apply [@guard](#guard) -on all of them at once. +A useful pattern is to group fields in an `extend type` to apply [@guard](#guard) on all of them at once. ```graphql extend type Query @guard { ... } ``` -The `@guard` directive will be prepended to other directives defined on the fields -and thus executes before them. +The `@guard` directive will be prepended to other directives defined on the fields and thus executes before them. ```graphql extend type Query { @@ -1569,8 +1539,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -1673,8 +1642,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model is different than the field name, -you can override it by setting `relation`. +If the name of the relationship on the Eloquent model is different than the field name, you can override it by setting `relation`. ```graphql type User { @@ -1729,8 +1697,7 @@ directive @inject( ) repeatable on FIELD_DEFINITION ``` -This is useful to ensure that the authenticated user's `id` is -automatically used for creating new models and cannot be manipulated. +This is useful to ensure that the authenticated user's `id` is automatically used for creating new models and cannot be manipulated. ```graphql type Mutation { @@ -1740,8 +1707,7 @@ type Mutation { } ``` -If you are using an Input Object as an argument, you can use dot notation to -set a nested argument. +If you are using an Input Object as an argument, you can use dot notation to set a nested argument. ```graphql type Mutation { @@ -1767,8 +1733,7 @@ directive @interface( ) on INTERFACE ``` -Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding -to use this directive, you probably don't need it. +Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding to use this directive, you probably don't need it. Set the `resolveType` argument to a function that returns the implementing Object Type. @@ -1779,8 +1744,8 @@ interface Commentable } ``` -The function receives the value of the parent field as its single argument and must -return an Object Type. You can get the appropriate Object Type from Lighthouse's type registry. +The function receives the value of the parent field as its single argument and must return an Object Type. +You can get the appropriate Object Type from Lighthouse's type registry. ```php namespace App\GraphQL\Interfaces; @@ -1956,8 +1921,7 @@ Ensure the order of the argument definition matches the parameters of your metho public function purchasedItemsCount(int $year, ?bool $includeReturns) ``` -Lighthouse will always pass down the same number of arguments and default to `null` -if the client passes nothing. +Lighthouse will always pass down the same number of arguments and default to `null` if the client passes nothing. ```graphql { @@ -2211,8 +2175,7 @@ The arguments are a map from directive names to namespaces. directive @namespace repeatable on FIELD_DEFINITION | OBJECT ``` -The following example applies the namespace `App\Blog` -to the [@field](#field) directive used on the `posts` field. +The following example applies the namespace `App\Blog` to the [@field](#field) directive used on the `posts` field. ```graphql type Query { @@ -2222,9 +2185,8 @@ type Query { } ``` -When used upon an object type or an object type extension, the namespace -applies to fields of the type as well. This allows you to specify -a common namespace for a group of fields. +When used upon an object type or an object type extension, the namespace applies to fields of the type as well. +This allows you to specify a common namespace for a group of fields. ```graphql extend type Query @namespace(field: "App\\Blog") { @@ -2322,8 +2284,7 @@ directive @node( ) on OBJECT ``` -Lighthouse defaults to resolving types through the underlying model, -for example by calling `User::find($id)`. +Lighthouse defaults to resolving types through the underlying model, for example by calling `User::find($id)`. ```graphql type User @node { @@ -2339,8 +2300,7 @@ type Country @node(resolver: "App\\Countries@byId") { } ``` -The `resolver` argument has to specify a function which will be passed the -decoded `id` and resolves to a result. +The `resolver` argument has to specify a function which will be passed the decoded `id` and resolves to a result. ```php public function byId($id): array { @@ -2353,8 +2313,7 @@ public function byId($id): array { [Read more](../digging-deeper/relay.md#global-object-identification). -Behind the scenes, Lighthouse will decode the global id sent from the client -to find the model by it's primary id in the database. +Behind the scenes, Lighthouse will decode the global id sent from the client to find the model by it's primary id in the database. ## @notIn @@ -2626,9 +2585,8 @@ It can be queried like this: ### Pagination type -The `type` of pagination defaults to `PAGINATOR`, but may also be set to -`SIMPLE` (see [Simple Pagination](#simple-pagination)) or a Relay compliant -`CONNECTION`. +The `type` of pagination defaults to `PAGINATOR`. +May also be set to `SIMPLE` (see [Simple Pagination](#simple-pagination)) or a Relay compliant `CONNECTION`. > Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -2673,9 +2631,8 @@ type PostEdge { ### Simple Pagination -In contrast to other pagination types, `SIMPLE` pagination only fires a single database -query on every request. This improves performance, but means that the response does not -hold information about the total number of items. +In contrast to other pagination types, `SIMPLE` pagination only fires a single database query on every request. +This improves performance, but means that the response does not hold information about the total number of items. If you wish to use the `simplePaginate` method, set the `type` to `SIMPLE`. @@ -2773,9 +2730,8 @@ query { ### Limit maximum count -Lighthouse allows you to specify a global maximum for the number of items a user -can request through pagination through the config. You may also overwrite this -per field with the `maxCount` argument: +Lighthouse allows you to specify a global maximum for the number of items a user can request through pagination through the config. +You may also overwrite this per field with the `maxCount` argument: ```graphql type Query { @@ -2785,8 +2741,8 @@ type Query { ### Overwrite model -By default, Lighthouse looks for an Eloquent model in the configured default namespace, with the same -name as the returned type. You can overwrite this by setting the `model` argument. +By default, Lighthouse looks for an Eloquent model in the configured default namespace, with the same name as the returned type. +You can overwrite this by setting the `model` argument. ```graphql type Query { @@ -2832,7 +2788,8 @@ class Blog You can provide your own function that resolves the field by directly returning data in a `\Illuminate\Contracts\Pagination\Paginator` instance. -This is mutually exclusive with `builder` and `model`. Not compatible with `scopes` and builder arguments such as `@eq`. +This is mutually exclusive with `builder` and `model`. +Not compatible with `scopes` and builder arguments such as `@eq`. ```graphql type Query { @@ -2888,8 +2845,7 @@ directive @rename( ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -This can often be useful to ensure consistent naming of your schema -without having to change the underlying models. +This can often be useful to ensure consistent naming of your schema without having to change the underlying models. ```graphql type User { @@ -3132,8 +3088,7 @@ directive @search( ) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -The `search()` method of the model is called with the value of the argument, -using the driver you configured for [Laravel Scout](https://laravel.com/docs/scout). +The `search()` method of the model is called with the value of the argument, using the driver you configured for [Laravel Scout](https://laravel.com/docs/scout). ```graphql type Query { @@ -3141,8 +3096,7 @@ type Query { } ``` -The [@search](#search) directive only works in combination with filter directives that -implement `\Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: +The [@search](#search) directive only works in combination with filter directives that implement `\Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: - [@eq](#eq) - [@softDeletes](#softdeletes) @@ -3228,8 +3182,7 @@ mutation { } ``` -Internally, the arguments will be transformed into a flat structure before -they are passed along to the resolver: +Internally, the arguments will be transformed into a flat structure before they are passed along to the resolver: ```php [ @@ -3239,8 +3192,7 @@ they are passed along to the resolver: ] ``` -Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/argument-directives.md) -have been applied, e.g. validation, transformation. +Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/argument-directives.md) have been applied, e.g. validation, transformation. ## @subscription @@ -3257,8 +3209,8 @@ directive @subscription( ) on FIELD_DEFINITION ``` -If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md) -you do not need this directive. It is only useful if you need to override the default namespace. +If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md) you do not need this directive. +It is only useful if you need to override the default namespace. ```graphql type Subscription { @@ -3296,11 +3248,11 @@ directive @throttle( ) on FIELD_DEFINITION ``` -Allows use Laravel throttling on a per-field basis. See [Laravel doc](https://laravel.com/docs/routing#rate-limiting) -on how to configure named limiters. +Allows use Laravel throttling on a per-field basis. +See [Laravel doc](https://laravel.com/docs/routing#rate-limiting) on how to configure named limiters. -Limiters that return `response` are not supported. Hashes are different from the ones of Laravel, so one can't use -one named limiter to limit both Laravel route and GraphQL field. +Limiters that return `response` are not supported. +Hashes are different from the ones of Laravel, so one can't use one named limiter to limit both Laravel route and GraphQL field. ## @trashed @@ -3316,8 +3268,7 @@ directive @trashed on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION The most convenient way to use this directive is through [@softDeletes](#softdeletes). -If you want to add it manually, make sure the argument is of the -enum type `Trashed`: +If you want to add it manually, make sure the argument is of the enum type `Trashed`: ```graphql type Query { @@ -3354,8 +3305,7 @@ type Mutation { } ``` -If you want this for all your fields, consider adding this directive to your -global field middleware in `lighthouse.php`: +If you want this for all your fields, consider adding this directive to your global field middleware in `lighthouse.php`: ```php 'field_middleware' => [ @@ -3380,8 +3330,7 @@ directive @union( ) on UNION ``` -Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding -to use this directive, you probably don't need it. +Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding to use this directive, you probably don't need it. ```graphql type User { @@ -3397,8 +3346,7 @@ union Person @union(resolveType: "App\\GraphQL\\Unions\\Person@resolveType") = | Employee ``` -The function receives the value of the parent field as its single argument and must -resolve an Object Type from Lighthouse's `TypeRegistry`. +The function receives the value of the parent field as its single argument and must resolve an Object Type from Lighthouse's `TypeRegistry`. ```php namespace App\GraphQL\Unions; @@ -3477,8 +3425,7 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, or is located in a non-default namespace, set it with the `model` argument. ```graphql type Mutation { @@ -3660,7 +3607,7 @@ directive @whereAuth( > This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). -The following query returns all posts that belong to the currently authenticated user. +The following query returns all posts that belong to the currently authenticated user. Behind the scenes it is using a `whereHas` query. ```graphql @@ -3703,8 +3650,8 @@ input DateRange { } ``` -You may use any custom `input` type for the argument. Make sure it has -exactly two required fields to ensure the query is valid. +You may use any custom `input` type for the argument. +Make sure it has exactly two required fields to ensure the query is valid. ## @whereConditions @@ -3800,8 +3747,7 @@ directive @with( ) repeatable on FIELD_DEFINITION ``` -This can be a useful optimization for fields that are not returned directly -but rather used for resolving other fields. +This can be a useful optimization for fields that are not returned directly but rather used for resolving other fields. ```graphql type User { @@ -3809,8 +3755,7 @@ type User { } ``` -If you just want to return the relation itself as-is, -look into [handling Eloquent relationships](../eloquent/relationships.md). +If you just want to return the relation itself as-is, look into [handling Eloquent relationships](../eloquent/relationships.md). ## @withCount diff --git a/docs/5/api-reference/scalars.md b/docs/5/api-reference/scalars.md index 3490a64101..a4d06c484f 100644 --- a/docs/5/api-reference/scalars.md +++ b/docs/5/api-reference/scalars.md @@ -1,7 +1,6 @@ # Scalars -You can use Lighthouse's built-in scalars by defining them in your schema, -using [@scalar](directives.md#scalar) to point them to a FQCN. +You can use Lighthouse's built-in scalars by defining them in your schema, using [@scalar](directives.md#scalar) to point them to a FQCN. ```graphql "A datetime string with format `Y-m-d H:i:s`, e.g. `2018-05-23 13:43:32`." @@ -66,6 +65,4 @@ scalar Upload This Scalar can only be used as an argument, not as a return type. For more information, please refer to the [file uploads guide](../digging-deeper/file-uploads.md). -The multipart form request is handled by Lighthouse, the resolver gets passed -an instance of [`\Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) -in the argument `array $variables`. +The multipart form request is handled by Lighthouse, the resolver gets passed an instance of [`\Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) in the argument `array $variables`. diff --git a/docs/5/concepts/arg-resolvers.md b/docs/5/concepts/arg-resolvers.md index 790478a0a7..d13993f2c3 100644 --- a/docs/5/concepts/arg-resolvers.md +++ b/docs/5/concepts/arg-resolvers.md @@ -1,26 +1,20 @@ # Arg Resolvers -To understand the concept behind arg resolvers, you should familiarize yourself with -[how field resolvers are composed](https://graphql.org/learn/execution). +To understand the concept behind arg resolvers, you should familiarize yourself with [how field resolvers are composed](https://graphql.org/learn/execution). ## Motivation -Arg resolvers are an extension of the ideas behind GraphQL field execution, -applied to input arguments. Since GraphQL queries can be used to fetch complex -and deeply nested data from the client, it is natural to assume that such complex -data can also be passed as the input arguments to a query. +Arg resolvers are an extension of the ideas behind GraphQL field execution, applied to input arguments. +Since GraphQL queries can be used to fetch complex and deeply nested data from the client, it is natural to assume that such complex data can also be passed as the input arguments to a query. -GraphQL's execution engine allows you to write small and focused field resolver functions -that only care about returning the data that it is immediately responsible for. +GraphQL's execution engine allows you to write small and focused field resolver functions that only care about returning the data that it is immediately responsible for. That makes the code much simpler and avoids duplication. -However, a single field resolver still has to take care of all the input arguments that -are passed to it. Handling complex input data in a single function is hard because of their -dynamic nature. The input given by a client might be nested arbitrarily deep -and come in many different variations. +However, a single field resolver still has to take care of all the input arguments that are passed to it. +Handling complex input data in a single function is hard because of their dynamic nature. +The input given by a client might be nested arbitrarily deep and come in many different variations. -The following example shows an example mutation that is actually composed out of multiple -distinct operations. +The following example shows an example mutation that is actually composed out of multiple distinct operations. ```graphql type Mutation { @@ -38,8 +32,7 @@ input CreateNoteInput { } ``` -In a single request, we can pass all data relating to a task, -including related entities such as notes. +In a single request, we can pass all data relating to a task, including related entities such as notes. ```graphql mutation CreateTaskWithNotes { @@ -77,18 +70,16 @@ function createTaskWithNotes($root, array $args): \App\Models\Task { } ``` -In this contrived example, the function is still pretty simple. However, separation of concerns -is already violated: A single function is responsible for creating both tasks and notes. +In this contrived example, the function is still pretty simple. +However, separation of concerns is already violated: A single function is responsible for creating both tasks and notes. -We might want to extend our schema to support more operations in the future, such as updating -a task and creating, updating or deleting notes or other, more deeply nested relations. +We might want to extend our schema to support more operations in the future, such as updating a task and creating, updating or deleting notes or other, more deeply nested relations. Such changes would force us to duplicate code and increase the complexity of our single function. ## Solution -Ideally, we would want to write small and focused functions that each deal with just -a part of the given input arguments. The execution engine should traverse the given -input and take care of calling the appropriate functions with their respective arguments. +Ideally, we would want to write small and focused functions that each deal with just a part of the given input arguments. +The execution engine should traverse the given input and take care of calling the appropriate functions with their respective arguments. ```php function createTask($root, array $args): \App\Models\Task { @@ -128,8 +119,7 @@ input CreateNoteInput { The [@create](../api-reference/directives.md#create) directive will behave differently, based on the context where it is used. -On the `createTask` field, it will create a `Task` model with the given `name`, save it -to the database and return that instance to Lighthouse. +On the `createTask` field, it will create a `Task` model with the given `name`, save it to the database and return that instance to Lighthouse. A simplified, generic implementation of an appropriate field resolver would look something like this: @@ -166,8 +156,7 @@ class CreateDirective extends BaseDirective implements FieldResolver ``` The arguments that are nested within `notes` will be handled as a nested argument resolver. -For each `CreateNoteInput`, the resolver will be called with the previously created `Task` -and create and attach a related `Note` model. +For each `CreateNoteInput`, the resolver will be called with the previously created `Task` and create and attach a related `Note` model. We can extend our previous implementation of [@create](../api-reference/directives.md#create) by allowing it to be used as an `ArgResolver`: diff --git a/docs/5/concepts/request-lifecycle.md b/docs/5/concepts/request-lifecycle.md index 0f02427f5a..e4f9716ea5 100644 --- a/docs/5/concepts/request-lifecycle.md +++ b/docs/5/concepts/request-lifecycle.md @@ -5,8 +5,7 @@ This section should provide an understanding of the involved steps, their order ## Routing -All requests to the configured GraphQL endpoint - usually `/graphql` - are routed -to the single `GraphQLController`. +All requests to the configured GraphQL endpoint - usually `/graphql` - are routed to the single `GraphQLController`. ## HTTP Middleware @@ -27,18 +26,17 @@ This step is typically cached for larger schemas, to enhance performance. ## Query Validation -The GraphQL query is validated to ensure it matches the schema. Lighthouse makes sure the requested -fields are available in the schema, and the correct variables are passed. +The GraphQL query is validated to ensure it matches the schema. +Lighthouse makes sure the requested fields are available in the schema, and the correct variables are passed. ## Field Execution Starting from the root level, the fields within the query are executed. -Each field may be wrapped with field middleware, which can add authentication, authorization, -fine-grained validation, and more. Finally, the field resolver is called to produce a value for the field. +Each field may be wrapped with field middleware, which can add authentication, authorization, fine-grained validation, and more. +Finally, the field resolver is called to produce a value for the field. -If the field contains a subselection, the same process happens for the nested fields, until -we either abort with an error or traversed the entire query tree. +If the field contains a subselection, the same process happens for the nested fields, until we either abort with an error or traversed the entire query tree. [Learn more about GraphQL execution](https://graphql.org/learn/execution). @@ -50,4 +48,5 @@ Lighthouse collects the errors to allow the rest of the query to execute. ## Result Assembly The execution results are assembled into a structure that resembles the query of the client. -Errors are properly formatted and included in the response. The response is sent to the client. +Errors are properly formatted and included in the response. +The response is sent to the client. diff --git a/docs/5/custom-directives/argument-directives.md b/docs/5/custom-directives/argument-directives.md index b2bbeab038..1c0b184c22 100644 --- a/docs/5/custom-directives/argument-directives.md +++ b/docs/5/custom-directives/argument-directives.md @@ -2,8 +2,7 @@ Argument directives can be applied to a [InputValueDefinition](https://graphql.github.io/graphql-spec/June2018/#InputValueDefinition). -As arguments may be contained within a list in the schema definition, you must specify -what your argument should apply to in addition to its function. +As arguments may be contained within a list in the schema definition, you must specify what your argument should apply to in addition to its function. - If it applies to the individual items within the list, implement the [`\Nuwave\Lighthouse\Support\Contracts\ArgDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgDirective.php) interface. @@ -14,8 +13,7 @@ You must implement exactly one of those two interfaces in order for an argument ## Evaluation Order -The application of directives that implement the `ArgDirective` interface is -split into three distinct phases: +The application of directives that implement the `ArgDirective` interface is split into three distinct phases: - Sanitize: Clean the input, e.g. trim whitespace. Directives can hook into this phase by implementing `ArgSanitizerDirective`. @@ -39,8 +37,7 @@ In the given example, Lighthouse will take the value of the `password` argument ## ArgSanitizerDirective -An [`\Nuwave\Lighthouse\Support\Contracts\ArgSanitizerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgSanitizerDirective.php) -takes an incoming value and returns a new value. +An [`\Nuwave\Lighthouse\Support\Contracts\ArgSanitizerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgSanitizerDirective.php) takes an incoming value and returns a new value. Let's take a look at the built-in [@trim](../api-reference/directives.md#trim) directive. @@ -74,8 +71,8 @@ GRAPHQL; } ``` -The `sanitize` method takes an argument which represents the actual incoming value that is given -to an argument in a query and is expected to modify the value, if needed, and return it. +The `sanitize` method takes an argument which represents the actual incoming value that is given to an argument in a query and is expected to modify the value, if needed. +Return it. For example, if we have the following schema. @@ -106,8 +103,7 @@ class CreateUser ## ArgTransformerDirective -An [`\Nuwave\Lighthouse\Support\Contracts\ArgTransformerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgTransformerDirective.php) -works essentially the same as an [`ArgSanitizerDirective`](#argsanitizerdirective). +An [`\Nuwave\Lighthouse\Support\Contracts\ArgTransformerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgTransformerDirective.php) works essentially the same as an [`ArgSanitizerDirective`](#argsanitizerdirective). Notable differences are: - The method to implement is called `transform` @@ -115,9 +111,7 @@ Notable differences are: ## ArgBuilderDirective -An [`\Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgBuilderDirective.php) -directive allows using arguments passed by the client to dynamically -modify the database query that Lighthouse creates for a field. +An [`\Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgBuilderDirective.php) directive allows using arguments passed by the client to dynamically modify the database query that Lighthouse creates for a field. Currently, the following directives use the defined filters for resolving the query: @@ -139,8 +133,7 @@ type User { } ``` -Passing the `category` argument will select only the user's posts -where the `category` column is equal to the value of the `category` argument. +Passing the `category` argument will select only the user's posts where the `category` column is equal to the value of the `category` argument. So let's take a look at the built-in [@eq](../api-reference/directives.md#eq) directive. @@ -189,8 +182,7 @@ The `handleBuilder` method takes two arguments: - `$value` The value of the argument value that [@eq](../api-reference/directives.md#eq) was applied on to. -If you want to use a more complex value for manipulating a query, -you can build a `ArgBuilderDirective` to work with lists or nested input objects. +If you want to use a more complex value for manipulating a query, you can build a `ArgBuilderDirective` to work with lists or nested input objects. Lighthouse's [@whereBetween](../api-reference/directives.md#wherebetween) is one example of this. ```graphql @@ -207,20 +199,16 @@ input DateRange { ## ArgResolver -An [`\Nuwave\Lighthouse\Support\Contracts\ArgResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgResolver.php) -directive allows you to compose resolvers for complex nested inputs, similar to the way -that field resolvers are composed together. +An [`\Nuwave\Lighthouse\Support\Contracts\ArgResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgResolver.php) directive allows you to compose resolvers for complex nested inputs, similar to the way that field resolvers are composed together. -For an in-depth explanation of the concept of composing arg resolvers, -read the [explanation of arg resolvers](../concepts/arg-resolvers.md). +For an in-depth explanation of the concept of composing arg resolvers, read the [explanation of arg resolvers](../concepts/arg-resolvers.md). ## ArgManipulator -An [`\Nuwave\Lighthouse\Support\Contracts\ArgManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgManipulator.php) -directive can be used to manipulate the schema AST. +An [`\Nuwave\Lighthouse\Support\Contracts\ArgManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgManipulator.php) directive can be used to manipulate the schema AST. -For example, you might want to add a directive that automagically derives the arguments -for a field based on an object type. A skeleton for this directive might look something like this: +For example, you might want to add a directive that automagically derives the arguments for a field based on an object type. +A skeleton for this directive might look something like this: ```php namespace App\GraphQL\Directives; diff --git a/docs/5/custom-directives/field-directives.md b/docs/5/custom-directives/field-directives.md index abaf81c1db..bf6ddef117 100644 --- a/docs/5/custom-directives/field-directives.md +++ b/docs/5/custom-directives/field-directives.md @@ -4,18 +4,15 @@ Field directives can be applied to any [FieldDefinition](https://graphql.github. ## FieldResolver -Perhaps the most important directive interface, a [`\Nuwave\Lighthouse\Support\Contracts\FieldResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldResolver.php) -lets you add a resolver for a field through a directive. +Perhaps the most important directive interface, a [`\Nuwave\Lighthouse\Support\Contracts\FieldResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldResolver.php) lets you add a resolver for a field through a directive. It can be a great way to reuse resolver logic within a schema. ## FieldMiddleware -A [`\Nuwave\Lighthouse\Support\Contracts\FieldMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldMiddleware.php) directive allows you -to wrap around the field resolver, just like [Laravel Middleware](https://laravel.com/docs/middleware). +A [`\Nuwave\Lighthouse\Support\Contracts\FieldMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldMiddleware.php) directive allows you to wrap around the field resolver, just like [Laravel Middleware](https://laravel.com/docs/middleware). -You may use it to handle incoming values before reaching the final resolver -as well as the outgoing result of resolving the field. +You may use it to handle incoming values before reaching the final resolver as well as the outgoing result of resolving the field. ```php namespace App\GraphQL\Directives; @@ -72,8 +69,7 @@ type Query { ## FieldBuilderDirective -A [`\Nuwave\Lighthouse\Support\Contracts\FieldBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/FieldBuilderDirective.php) -directive allows modifying the database query that Lighthouse creates for a field. +A [`\Nuwave\Lighthouse\Support\Contracts\FieldBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/FieldBuilderDirective.php) directive allows modifying the database query that Lighthouse creates for a field. > This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](../api-reference/directives.md#all) or [@hasMany](../api-reference/directives.md#hasmany). @@ -84,17 +80,14 @@ The following directives use the defined filter for resolving the query: ## FieldManipulator -A [`\Nuwave\Lighthouse\Support\Contracts\FieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldManipulator.php) -directive can be used to manipulate the schema AST. +A [`\Nuwave\Lighthouse\Support\Contracts\FieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldManipulator.php) directive can be used to manipulate the schema AST. ## ValidationDirective -This directive type is implemented as an abstract class rather than a pure interface and allows -you to define complex validation rules for a field with ease. +This directive type is implemented as an abstract class rather than a pure interface and allows you to define complex validation rules for a field with ease. [Read more about it in the Validation section](../security/validation.md#validate-fields). ## ComplexityResolverDirective -A [`\Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ComplexityResolverDirective.php) -directive allows you to overwrite the default query complexity calculation. +A [`\Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ComplexityResolverDirective.php) directive allows you to overwrite the default query complexity calculation. diff --git a/docs/5/custom-directives/getting-started.md b/docs/5/custom-directives/getting-started.md index d98021f596..f450a41283 100644 --- a/docs/5/custom-directives/getting-started.md +++ b/docs/5/custom-directives/getting-started.md @@ -3,8 +3,7 @@ As you grow your GraphQL schema, you may find the need for more specialized functionality. Learn how you can abstract logic in a composable and reusable manner by using custom directives. -Directives are implemented as PHP classes, each directive available -in the schema corresponds to a single class. +Directives are implemented as PHP classes, each directive available in the schema corresponds to a single class. ## Naming Convention @@ -18,8 +17,7 @@ Use the artisan generator command to create it: php artisan lighthouse:directive --argument upperCase -That will create a class called `UpperCaseDirective` that extends the -abstract class `\Nuwave\Lighthouse\Schema\Directives\BaseDirective`. +That will create a class called `UpperCaseDirective` that extends the abstract class `\Nuwave\Lighthouse\Schema\Directives\BaseDirective`. ```php use Nuwave\Lighthouse\Schema\Directives\BaseDirective; @@ -51,12 +49,11 @@ GRAPHQL; ## Directive Interfaces At this point, the directive does not do anything. -Depending on what your directive should do, you can pick one or more of the provided -directive interfaces to add functionality. They serve as the point of contact to Lighthouse. +Depending on what your directive should do, you can pick one or more of the provided directive interfaces to add functionality. +They serve as the point of contact to Lighthouse. In this case, our directive needs to run after the actual resolver. -Just like [Laravel Middleware](https://laravel.com/docs/middleware), -we can wrap around it by using the `FieldMiddleware` directive. +Just like [Laravel Middleware](https://laravel.com/docs/middleware), we can wrap around it by using the `FieldMiddleware` directive. ```php namespace App\GraphQL\Directives; @@ -108,13 +105,12 @@ class UpperCaseDirective extends BaseDirective implements FieldMiddleware Now that we defined and implemented the directive, how can Lighthouse find it? -When Lighthouse encounters a directive within the schema, it starts looking for a matching class -in the following order: +When Lighthouse encounters a directive within the schema, it starts looking for a matching class in the following order: 1. User-defined namespaces as configured in `config/lighthouse.php`, defaults to `App\GraphQL\Directives` 1. The [RegisterDirectiveNamespaces](../api-reference/events.md#registerdirectivenamespaces) event is dispatched to gather namespaces defined by plugins, extensions or other listeners 1. Lighthouse's built-in directive namespace -This means that our directive is already registered, just by matter of defining it in the default namespace, -and will take precedence over potential other directives with the same name. +This means that our directive is already registered, just by matter of defining it in the default namespace. +Will take precedence over potential other directives with the same name. diff --git a/docs/5/custom-directives/type-directives.md b/docs/5/custom-directives/type-directives.md index ddf4fa808d..3ab38263a6 100644 --- a/docs/5/custom-directives/type-directives.md +++ b/docs/5/custom-directives/type-directives.md @@ -6,18 +6,15 @@ These directives can generally be applied to [type definitions](../the-basics/ty ## TypeManipulator -The [`\Nuwave\Lighthouse\Support\Contracts\TypeManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeManipulator.php) -interface can be used to manipulate the AST from a type definition node. +The [`\Nuwave\Lighthouse\Support\Contracts\TypeManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeManipulator.php) interface can be used to manipulate the AST from a type definition node. ## TypeMiddleware -The [`\Nuwave\Lighthouse\Support\Contracts\TypeMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeMiddleware.php) -interface allows access to an AST node as it is converted to an executable type. +The [`\Nuwave\Lighthouse\Support\Contracts\TypeMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeMiddleware.php) interface allows access to an AST node as it is converted to an executable type. ## TypeResolver -The [`\Nuwave\Lighthouse\Support\Contracts\TypeResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeResolver.php) -interface can be used for custom conversion from AST values to an executable type. +The [`\Nuwave\Lighthouse\Support\Contracts\TypeResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeResolver.php) interface can be used for custom conversion from AST values to an executable type. ## Type Extension Directives @@ -25,5 +22,4 @@ These directives can generally be applied to [type extensions](https://graphql.g ## TypeExtensionManipulator -The [`\Nuwave\Lighthouse\Support\Contracts\TypeExtensionManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeExtensionManipulator.php) -interface can be used to manipulate the AST from a type extension node. +The [`\Nuwave\Lighthouse\Support\Contracts\TypeExtensionManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeExtensionManipulator.php) interface can be used to manipulate the AST from a type extension node. diff --git a/docs/5/digging-deeper/adding-types-programmatically.md b/docs/5/digging-deeper/adding-types-programmatically.md index 97ba9afa35..5389fe923e 100644 --- a/docs/5/digging-deeper/adding-types-programmatically.md +++ b/docs/5/digging-deeper/adding-types-programmatically.md @@ -4,9 +4,7 @@ You might want to add additional types to the schema programmatically. ## Additional Schema Definitions -If you want to use the SDL to define additional types dynamically, -you can listen for the [`BuildSchemaString`](../api-reference/events.md#buildschemastring) -event and return additional schema definitions as a string: +If you want to use the SDL to define additional types dynamically, you can listen for the [`BuildSchemaString`](../api-reference/events.md#buildschemastring) event and return additional schema definitions as a string: ```php $dispatcher = app(\Illuminate\Contracts\Events\Dispatcher::class); @@ -18,8 +16,7 @@ $dispatcher->listen( ); ``` -When your schema is defined within files and you want to use `#import` to combine them, -you can use the `\Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: +When your schema is defined within files and you want to use `#import` to combine them, you can use the `\Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: ```php $stitcher = new \Nuwave\Lighthouse\Schema\Source\SchemaStitcher(__DIR__ . '/path/to/schema.graphql'); @@ -30,11 +27,9 @@ return $stitcher->getSchemaString(); While Lighthouse is an SDL-first GraphQL server, you can also use native PHP type definitions. -Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) -on how to define types. +Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) on how to define types. -Note that you will not have access to a large portion of Lighthouse functionality -that is provided through server-side directives and the definition is much more verbose. +Note that you will not have access to a large portion of Lighthouse functionality that is provided through server-side directives and the definition is much more verbose. Because of this, we do not recommend you use native PHP types for complex object types. diff --git a/docs/5/digging-deeper/client-directives.md b/docs/5/digging-deeper/client-directives.md index dceb1c81b5..e9b7207d78 100644 --- a/docs/5/digging-deeper/client-directives.md +++ b/docs/5/digging-deeper/client-directives.md @@ -4,17 +4,16 @@ Client directives allow clients to change the behaviour of query execution. > Client directives must not be used within your schema definition. -The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) -mentions two client directives: [@skip](#skip) and [@include](#include). +The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) mentions two client directives. +[@skip](#skip) and [@include](#include). Both are built-in to Lighthouse and work out-of-the-box. ## @skip -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional -exclusion during execution as described by the `if` argument. +The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional exclusion during execution as described by the `if` argument. ```graphql directive @skip( @@ -36,11 +35,10 @@ query myQuery($someTest: Boolean) { ## @include -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments, -and allows for conditional inclusion during execution as described by the `if` argument. +The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional inclusion during execution as described by the `if` argument. ```graphql directive @include( @@ -74,19 +72,17 @@ directive @example( ``` By itself, a custom client directive does not do anything. -Lighthouse provides a class to retrieve information about where client directives -were placed in the query and what arguments were given to them. +Lighthouse provides a class to retrieve information about where client directives were placed in the query and what arguments were given to them. ```php $clientDirective = new \Nuwave\Lighthouse\ClientDirectives\ClientDirective('example'); ``` -The most common use case for a client directive is to place it on a field. There is a caveat -to working with this that is unintuitive at first: There might be multiple nodes referencing a single -field, and each of those may or may not have the client directive set, with possibly different arguments. +The most common use case for a client directive is to place it on a field. +There is a caveat to working with this that is unintuitive at first: There might be multiple nodes referencing a single field. +Each of those may or may not have the client directive set, with possibly different arguments. -The following example illustrates how a field `foo` can be referenced three times with different -configurations of a client directive: +The following example illustrates how a field `foo` can be referenced three times with different configurations of a client directive: ```graphql { @@ -98,8 +94,7 @@ configurations of a client directive: } ``` -You can get all arguments for every node that is referencing the field you are currently -resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): +You can get all arguments for every node that is referencing the field you are currently resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): ```php $arguments = $clientDirective->forField($resolveInfo); @@ -116,8 +111,8 @@ For the example query above, it will look like this: ] ``` -You are then free to implement whatever logic on top of that. Some client directives may require -only one field node to have it set, whereas others might require all of them to have the same configuration. +You are then free to implement whatever logic on top of that. +Some client directives may require only one field node to have it set, whereas others might require all of them to have the same configuration. > There are other locations where client directives may be used on: https://spec.graphql.org/draft/#ExecutableDirectiveLocation > You can add a PR to Lighthouse if you need them. diff --git a/docs/5/digging-deeper/deprecation.md b/docs/5/digging-deeper/deprecation.md index 3a51c91688..27bf0d2e96 100644 --- a/docs/5/digging-deeper/deprecation.md +++ b/docs/5/digging-deeper/deprecation.md @@ -1,7 +1,6 @@ # Deprecation -The [@deprecated](../api-reference/directives.md#deprecated) directive allows marking elements -of a GraphQL schema as deprecated. +The [@deprecated](../api-reference/directives.md#deprecated) directive allows marking elements of a GraphQL schema as deprecated. ## Detect deprecated usage @@ -10,8 +9,8 @@ of a GraphQL schema as deprecated. Before you eventually remove deprecated elements, you want to give clients time to switch over. To be sure the elements are no longer in use, dynamic instrumentation is required. -Lighthouse allows you to register a handler function that is called with a list of deprecated -elements that were used in a query. Use a reporting mechanism of your choice to get notified. +Lighthouse allows you to register a handler function that is called with a list of deprecated elements that were used in a query. +Use a reporting mechanism of your choice to get notified. In order to not slow down your response times, use a terminating callback. ```php diff --git a/docs/5/digging-deeper/error-handling.md b/docs/5/digging-deeper/error-handling.md index 9b69bb8518..9137834f6d 100644 --- a/docs/5/digging-deeper/error-handling.md +++ b/docs/5/digging-deeper/error-handling.md @@ -1,23 +1,21 @@ # Error Handling -Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**, -so you can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). +Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**. +You can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). ## User-friendly Errors -In a production setting, error messages should not be shown to the user by default -to prevent information leaking. In some cases however, you may want to display an -explicit error message to the user. +In a production setting, error messages should not be shown to the user by default to prevent information leaking. +In some cases however, you may want to display an explicit error message to the user. -**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface, that can -be implemented by Exceptions to control how they are rendered to the client. +**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface. +Can be implemented by Exceptions to control how they are rendered to the client. Head over their [Error Handling docs](https://webonyx.github.io/graphql-php/error-handling) to learn more. ## Additional Error Information -The interface [`\Nuwave\Lighthouse\Exceptions\RendersErrorsExtensions`](https://github.com/nuwave/lighthouse/blob/master/src/Exceptions/RendersErrorsExtensions.php) -may be extended to add more information than just an error message to the rendered error output. +The interface [`\Nuwave\Lighthouse\Exceptions\RendersErrorsExtensions`](https://github.com/nuwave/lighthouse/blob/master/src/Exceptions/RendersErrorsExtensions.php) may be extended to add more information than just an error message to the rendered error output. This custom exception contains information about the reason the exception was thrown: @@ -78,8 +76,7 @@ class CustomException extends Exception implements RendersErrorsExtensions } ``` -Now you can just throw that Exception somewhere in your code, for example your resolver, -and it will display additional error output. +Now you can just throw that Exception somewhere in your code, for example your resolver, and it will display additional error output. ```php namespace App\GraphQL\Queries; @@ -165,11 +162,9 @@ final class ExtensionErrorHandler implements ErrorHandler ## Partial Errors -As a GraphQL query may return a partial result, you may not always want to abort -execution immediately after an error occurred. +As a GraphQL query may return a partial result, you may not always want to abort execution immediately after an error occurred. -Use the [`ErrorPool`](https://github.com/nuwave/lighthouse/blob/master/src/Execution/ErrorPool.php) -when you want to collect multiple errors before returning a result. +Use the [`ErrorPool`](https://github.com/nuwave/lighthouse/blob/master/src/Execution/ErrorPool.php) when you want to collect multiple errors before returning a result. ```php try { diff --git a/docs/5/digging-deeper/extending-lighthouse.md b/docs/5/digging-deeper/extending-lighthouse.md index 25c257f104..2a1588a9e5 100644 --- a/docs/5/digging-deeper/extending-lighthouse.md +++ b/docs/5/digging-deeper/extending-lighthouse.md @@ -1,12 +1,10 @@ # Extending Lighthouse -Lighthouse offers various extension points which can be utilized by package developers -as well as end users. +Lighthouse offers various extension points which can be utilized by package developers as well as end users. ## The Event System -Lighthouse offers a unified way of hooking into the complete execution lifecycle -through [Laravel's event system](https://laravel.com/docs/events). +Lighthouse offers a unified way of hooking into the complete execution lifecycle through [Laravel's event system](https://laravel.com/docs/events). You may use any Service Provider to register listeners. A complete list of all dispatched events is available [in the events API reference](../api-reference/events.md). @@ -42,25 +40,20 @@ The first priority when looking for a resolver is always given to `FieldResolver After that, Lighthouse attempts to find a default resolver. -The interface [`\Nuwave\Lighthouse\Support\Contracts\ProvidesResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ProvidesResolver.php) -is expected to provide a resolver in case no resolver directive is defined for a field. +The interface [`\Nuwave\Lighthouse\Support\Contracts\ProvidesResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ProvidesResolver.php) is expected to provide a resolver in case no resolver directive is defined for a field. -If the field is defined on the root `Query` or `Mutation` types, -Lighthouse's default implementation looks for a class with the capitalized name -of the field in the configured default location and calls its `__invoke` method. +If the field is defined on the root `Query` or `Mutation` types, Lighthouse's default implementation looks for a class with the capitalized name of the field in the configured default location and calls its `__invoke` method. Non-root fields fall back to [webonyx's default resolver](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver). You may overwrite this by passing a `callable` to `\GraphQL\Executor\Executor::setDefaultFieldResolver`. -When the field is defined on the root `Subscription` type, the [`\Nuwave\Lighthouse\Support\Contracts\ProvidesSubscriptionResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ProvidesSubscriptionResolver.php) -interface is used instead. +When the field is defined on the root `Subscription` type, the [`\Nuwave\Lighthouse\Support\Contracts\ProvidesSubscriptionResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ProvidesSubscriptionResolver.php) interface is used instead. ## Use a custom `GraphQLContext` The context is the third argument of any resolver function. -You may replace the default `\Nuwave\Lighthouse\Schema\Context` with your own -implementation of the interface `Nuwave\Lighthouse\Support\Contracts\GraphQLContext`. +You may replace the default `\Nuwave\Lighthouse\Schema\Context` with your own implementation of the interface `Nuwave\Lighthouse\Support\Contracts\GraphQLContext`. The following example is just a starting point of what you can do: ```php diff --git a/docs/5/digging-deeper/file-uploads.md b/docs/5/digging-deeper/file-uploads.md index 95a3b87f92..efdb10288f 100644 --- a/docs/5/digging-deeper/file-uploads.md +++ b/docs/5/digging-deeper/file-uploads.md @@ -1,7 +1,6 @@ # Uploading files -Lighthouse allows you to upload files using a multipart form request -as defined in [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec). +Lighthouse allows you to upload files using a multipart form request as defined in [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec). ## Setup @@ -25,11 +24,9 @@ type Mutation { ## Handling file uploads Lighthouse accepts multipart form requests that contain file uploads. -The given file is injected into the `array $variables` as an instance of [`\Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) -and passed into the resolver. +The given file is injected into the `array $variables` as an instance of [`\Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) and passed into the resolver. -It is up to you how to handle the given file in the resolver, -see the [Laravel docs for File Uploads](https://laravel.com/docs/filesystem#file-uploads). +It is up to you how to handle the given file in the resolver, see the [Laravel docs for File Uploads](https://laravel.com/docs/filesystem#file-uploads). The field from the previous example can be implemented like this: @@ -58,8 +55,7 @@ class Upload ## Client-side Usage In order to upload a file, you must send a `multipart/form-data` request. -Use any of the [available client implementations](https://github.com/jaydenseric/graphql-multipart-request-spec#client) -or look at the [specification examples](https://github.com/jaydenseric/graphql-multipart-request-spec#multipart-form-field-structure) to roll your own. +Use any of the [available client implementations](https://github.com/jaydenseric/graphql-multipart-request-spec#client) or look at the [specification examples](https://github.com/jaydenseric/graphql-multipart-request-spec#multipart-form-field-structure) to roll your own. > If you are using [the EnsureXHR middleware to protect against CSRF](../security/csrf.md), > add the header `X-Requested-With: XMLHttpRequest` to your request. diff --git a/docs/5/digging-deeper/ordering.md b/docs/5/digging-deeper/ordering.md index 175141ef5a..5c9819882b 100644 --- a/docs/5/digging-deeper/ordering.md +++ b/docs/5/digging-deeper/ordering.md @@ -2,8 +2,7 @@ ## Client Controlled Ordering -To enable clients to control the ordering, use [@orderBy](../api-reference/directives.md#orderby) on an argument of -a field that is backed by a database query. +To enable clients to control the ordering, use [@orderBy](../api-reference/directives.md#orderby) on an argument of a field that is backed by a database query. ```graphql type Query { @@ -11,9 +10,8 @@ type Query { } ``` -The type of the argument can be left blank as `_` , -as Lighthouse will automatically generate an input that takes enumerated column names, -together with the `SortOrder` enum, and add that to your schema: +The type of the argument can be left blank as `_` , as Lighthouse will automatically generate an input that takes enumerated column names, together with the `SortOrder` enum. +Add that to your schema: ```graphql "Order by clause for Query.posts.orderBy." diff --git a/docs/5/digging-deeper/relay.md b/docs/5/digging-deeper/relay.md index 4dce4838c7..272618e037 100644 --- a/docs/5/digging-deeper/relay.md +++ b/docs/5/digging-deeper/relay.md @@ -2,9 +2,7 @@ ## Cursor Connection -Relay requires a particular kind of pagination which is the [Cursor Connection](https://facebook.github.io/relay/graphql/connections.htm) -To get a relay-compatible connection on a root query field, use the [@paginate](../api-reference/directives.md#paginate) -directive with the pagination type `CONNECTION`. +Relay requires a particular kind of pagination which is the [Cursor Connection](https://facebook.github.io/relay/graphql/connections.htm) To get a relay-compatible connection on a root query field, use the [@paginate](../api-reference/directives.md#paginate) directive with the pagination type `CONNECTION`. > Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -15,11 +13,10 @@ type Query { } ``` -This automatically converts the type definition into a relay connection and constructs -the appropriate queries via the underlying Eloquent model. +This automatically converts the type definition into a relay connection and constructs the appropriate queries via the underlying Eloquent model. -Connections can also be used for subfields of a type, given they are defined as a HasMany-Relationship -in Eloquent. Use the [@hasMany](../api-reference/directives.md#hasmany) directive. +Connections can also be used for subfields of a type, given they are defined as a HasMany-Relationship in Eloquent. +Use the [@hasMany](../api-reference/directives.md#hasmany) directive. ```graphql type User { @@ -30,8 +27,7 @@ type User { ## Global Object Identification -You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global ids. +You may rebind the `\Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global ids. [Global Object Identification](https://facebook.github.io/relay/graphql/objectidentification.htm) @@ -41,8 +37,7 @@ own mechanism of encoding/decoding global ids. ## Input Object Mutations -Lighthouse makes it easy to follow the principle of using a -single field argument called `input`, just use the [@spread](../api-reference/directives.md#spread) directive. +Lighthouse makes it easy to follow the principle of using a single field argument called `input`, just use the [@spread](../api-reference/directives.md#spread) directive. ```graphql type Mutation { diff --git a/docs/5/digging-deeper/schema-organisation.md b/docs/5/digging-deeper/schema-organisation.md index fc97d49851..07598310b0 100644 --- a/docs/5/digging-deeper/schema-organisation.md +++ b/docs/5/digging-deeper/schema-organisation.md @@ -45,8 +45,7 @@ graphql/ |-- category.graphql ``` -To import all schema files in `blog/` in one go, use wildcard import syntax -(works like PHP's [glob function](https://php.net/manual/function.glob.php)). +To import all schema files in `blog/` in one go, use wildcard import syntax (works like PHP's [glob function](https://php.net/manual/function.glob.php)). ```graphql #import blog/*.graphql @@ -70,11 +69,10 @@ The definition is imported from `schema.graphql`: ``` Now you want to add queries to allow fetching posts. -While you could add it to the main `Query` type in `schema.graphql`, -it is generally preferable to colocate queries with the type they return. +While you could add it to the main `Query` type in `schema.graphql`, it is generally preferable to colocate queries with the type they return. -Make sure `schema.graphql` contains a `Query` type. You can add an empty type -if you don't have one there: +Make sure `schema.graphql` contains a `Query` type. +You can add an empty type if you don't have one there: ```graphql type Query @@ -95,5 +93,4 @@ extend type Query { The fields in the `extend type` definition are merged with those of the original type. Apart from object types `type`, you can also extend `input`, `interface` and `enum` types. -Lighthouse will merge the fields (or values) with the original definition and always -produce a single type in the final schema. +Lighthouse will merge the fields (or values) with the original definition and always produce a single type in the final schema. diff --git a/docs/5/eloquent/complex-where-conditions.md b/docs/5/eloquent/complex-where-conditions.md index df371ba8be..1cfd039804 100644 --- a/docs/5/eloquent/complex-where-conditions.md +++ b/docs/5/eloquent/complex-where-conditions.md @@ -2,10 +2,8 @@ **Experimental: not enabled by default, not guaranteed to be stable.** -Adding query conditions ad-hoc can be cumbersome and limiting when you require -manifold ways to filter query results. -Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients -and allow them to apply complex, dynamic WHERE conditions to queries. +Adding query conditions ad-hoc can be cumbersome and limiting when you require manifold ways to filter query results. +Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients and allow them to apply complex, dynamic WHERE conditions to queries. ## Setup @@ -23,8 +21,7 @@ Install the dependency [mll-lab/graphql-php-scalars](https://github.com/mll-lab/ ## Usage -You can use this feature through a set of schema directives that enhance fields -with advanced filter capabilities. +You can use this feature through a set of schema directives that enhance fields with advanced filter capabilities. ### @whereConditions @@ -83,8 +80,8 @@ type Person { } ``` -Lighthouse automatically generates definitions for an `Enum` type and an `Input` type -that are restricted to the defined columns, so you do not have to specify them by hand. +Lighthouse automatically generates definitions for an `Enum` type and an `Input` type that are restricted to the defined columns. +You do not have to specify them by hand. The blank type named `_` will be changed to the actual type. Here are the types that will be included in the compiled schema: @@ -134,8 +131,8 @@ input QueryPeopleWhereWhereConditionsRelation { } ``` -Alternatively to the `columns` argument, you can also use `columnsEnum` in case you -want to re-use a list of allowed columns. Here's how your schema could look like: +Alternatively to the `columns` argument, you can also use `columnsEnum` in case you want to re-use a list of allowed columns. +Here's how your schema could look like: ```graphql type Query { @@ -161,8 +158,7 @@ Instead of creating enums for the allowed columns, it will simply use the existi It is recommended to either use the `columns` or the `columnsEnum` argument. When you don't define any allowed columns, clients can specify arbitrary column names as a `String`. -This approach should by taken with care, as it carries -potential performance and security risks and offers little type safety. +This approach should by taken with care, as it carries potential performance and security risks and offers little type safety. A simple query for a person who is exactly 42 years old would look like this: @@ -174,8 +170,7 @@ A simple query for a person who is exactly 42 years old would look like this: } ``` -Note that the operator defaults to `EQ` (`=`) if not given, so you could -also omit it from the previous example and get the same result. +Note that the operator defaults to `EQ` (`=`) if not given, so you could also omit it from the previous example and get the same result. The following query gets actors over age 37 who either have red hair or are at least 150cm: @@ -200,8 +195,8 @@ The following query gets actors over age 37 who either have red hair or are at l } ``` -Some operators require passing lists of values - or no value at all. The following -query gets people that have no hair and blue-ish eyes: +Some operators require passing lists of values - or no value at all. +The following query gets people that have no hair and blue-ish eyes: ```graphql { @@ -275,8 +270,7 @@ directive @whereHasConditions( ) on ARGUMENT_DEFINITION ``` -This directive works very similar to [@whereConditions](#whereconditions), except that -the conditions are applied to a relation sub query: +This directive works very similar to [@whereConditions](#whereconditions), except that the conditions are applied to a relation sub query: ```graphql type Query { @@ -319,8 +313,7 @@ enum QueryPeopleHasRoleColumn { } ``` -A simple query for a person who has an access level of at least 5, through one of -their roles, looks like this: +A simple query for a person who has an access level of at least 5, through one of their roles, looks like this: ```graphql { @@ -355,10 +348,10 @@ This query would retrieve all persons, no matter if they have a role or not: ## Custom operator If Lighthouse's default `SQLOperator` does not fit your use case, you can register a custom operator class. -This may be necessary if your database uses different SQL operators then Lighthouse's default, -or you want to extend/restrict the allowed operators. +This may be necessary if your database uses different SQL operators then Lighthouse's default, or you want to extend/restrict the allowed operators. -First create a class that implements `\Nuwave\Lighthouse\WhereConditions\Operator`. For example: +First create a class that implements `\Nuwave\Lighthouse\WhereConditions\Operator`. +For example: ```php namespace App\GraphQL; @@ -410,9 +403,8 @@ Make sure to add it after Lighthouse's `\Nuwave\Lighthouse\WhereConditions\Where ## Custom handler -If you want to take advantage of the schema generation that [@whereConditions](#whereconditions) -and [@whereHasConditions](#wherehasconditions) provide, but customize the application of arguments -to the query builder, you can provide a custom handler. +If you want to take advantage of the schema generation that [@whereConditions](#whereconditions) and [@whereHasConditions](#wherehasconditions) provide. +Customize the application of arguments to the query builder, you can provide a custom handler. ```graphql type Query { @@ -422,8 +414,7 @@ type Query { } ``` -When a client passes `where`, your handler will be called with the query builder and -the passed conditions: +When a client passes `where`, your handler will be called with the query builder and the passed conditions: ```php namespace App; diff --git a/docs/5/eloquent/getting-started.md b/docs/5/eloquent/getting-started.md index 3bddb4057e..cd6ab0ebcb 100644 --- a/docs/5/eloquent/getting-started.md +++ b/docs/5/eloquent/getting-started.md @@ -26,8 +26,7 @@ type Query { } ``` -The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as -the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. +The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. The following query: @@ -55,8 +54,7 @@ Will return the following result: ## Pagination -You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to -query a large list of models in chunks. +You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to query a large list of models in chunks. ```graphql type Query { @@ -96,8 +94,7 @@ And can be queried like this: ## Adding Query Constraints -Lighthouse provides directives such as [@eq](../api-reference/directives.md#eq) -to enhance your queries with additional constraints. +Lighthouse provides directives such as [@eq](../api-reference/directives.md#eq) to enhance your queries with additional constraints. The following field definition allows clients to fetch a single User by ID. @@ -131,13 +128,11 @@ If found, the result will look like this: ## Ordering -Use the [@orderBy](../api-reference/directives.md#orderby) directive to sort -a result list by one or more given columns. +Use the [@orderBy](../api-reference/directives.md#orderby) directive to sort a result list by one or more given columns. ## Local Scopes -[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models -to specify reusable query constraints. +[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models to specify reusable query constraints. ```php use Illuminate\Database\Eloquent\Builder; @@ -152,8 +147,7 @@ class User extends Model } ``` -Directives that query models, such as [@all](../api-reference/directives.md#all) -or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: +Directives that query models, such as [@all](../api-reference/directives.md#all) or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: ```graphql type Query { @@ -245,8 +239,7 @@ The update may fail to find the model you provided and return `null`: ## Upsert -Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with -a given `id` or create it if it does not exist. +Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with a given `id` or create it if it does not exist. ```graphql type Mutation { @@ -281,7 +274,8 @@ mutation { ## Delete -Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. Dangerously easy. +Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. +Dangerously easy. ```graphql type Mutation { @@ -299,7 +293,8 @@ mutation { } ``` -This mutation will return the deleted object, so you will have a last chance to look at the data. Use it wisely. +This mutation will return the deleted object, so you will have a last chance to look at the data. +Use it wisely. ```json { diff --git a/docs/5/eloquent/nested-mutations.md b/docs/5/eloquent/nested-mutations.md index fad9f6ad85..497304ab29 100644 --- a/docs/5/eloquent/nested-mutations.md +++ b/docs/5/eloquent/nested-mutations.md @@ -1,12 +1,11 @@ # Nested Mutations -Lighthouse allows you to create, update or delete models and their associated relationships, -all in one single mutation. This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). +Lighthouse allows you to create, update or delete models and their associated relationships, all in one single mutation. +This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). ## Return Types Required -You have to define return types on your relationship methods so that Lighthouse -can detect them. +You have to define return types on your relationship methods so that Lighthouse can detect them. ```php use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -28,20 +27,17 @@ class Post extends Model ## Partial Failure By default, all mutations are wrapped in a database transaction. -If any of the nested operations fail, the whole mutation is aborted -and no changes are written to the database. +If any of the nested operations fail, the whole mutation is aborted and no changes are written to the database. You can change this setting [in the configuration](../getting-started/configuration.md). ## Polymorphic Relation Limitations -Because the GraphQL Specification does not support polymorphic Input types (yet), -the available functionality is limited. +Because the GraphQL Specification does not support polymorphic Input types (yet), the available functionality is limited. -It is not possible to have an argument that can contain different types, which -would be necessary to pass the attributes the different related models might have. -For now, we can only support cases where the input type does not change across related -models, e.g. connecting through an ID, disconnecting or deleting the relation. +It is not possible to have an argument that can contain different types. +Would be necessary to pass the attributes the different related models might have. +For now, we can only support cases where the input type does not change across related models, e.g. connecting through an ID, disconnecting or deleting the relation. See [this issue](https://github.com/nuwave/lighthouse/issues/900) for further discussion. @@ -50,8 +46,7 @@ See [this issue](https://github.com/nuwave/lighthouse/issues/900) for further di Lighthouse has no mechanism for fine-grained permissions of nested mutation operations. Field directives such as [@can](../api-reference/directives.md#can) apply to the whole field. -Make sure that fields with nested mutations are only available to users who are allowed -to execute all reachable nested mutations. +Make sure that fields with nested mutations are only available to users who are allowed to execute all reachable nested mutations. ## BelongsTo @@ -63,8 +58,7 @@ type Mutation { } ``` -The mutation takes a single argument `input` that contains data about -the Post you want to create. +The mutation takes a single argument `input` that contains data about the Post you want to create. ```graphql input CreatePostInput { @@ -73,8 +67,7 @@ input CreatePostInput { } ``` -The first argument `title` is a value of the `Post` itself and corresponds -to a column in the database. +The first argument `title` is a value of the `Post` itself and corresponds to a column in the database. The second argument `author` is named just like the relationship method that is defined on the `Post` model. A nested `BelongsTo` relationship exposes the following operations: @@ -107,8 +100,7 @@ input CreateUserInput { } ``` -To create a new model and connect it to an existing model, -just pass the ID of the model you want to associate. +To create a new model and connect it to an existing model, just pass the ID of the model you want to associate. ```graphql mutation { @@ -136,8 +128,7 @@ Lighthouse will create a new `Post` and associate an `User` with it. } ``` -If the related model does not exist yet, you can also -create a new one. +If the related model does not exist yet, you can also create a new one. ```graphql mutation { @@ -166,8 +157,7 @@ mutation { ``` When issuing an update, you can also allow the user to remove a relation. -Both `disconnect` and `delete` remove the association to the author, -but `delete` also removes the author model itself. +Both `disconnect` and `delete` remove the association to the author, but `delete` also removes the author model itself. ```graphql type Mutation { @@ -191,8 +181,7 @@ input UpdateUserBelongsTo { ``` You must pass a truthy value to `disconnect` and `delete` for them to actually run. -This structure was chosen as it is consistent with updating `BelongsToMany` relationships -and allows the query string to be mostly static, taking a variable value to control its behaviour. +This structure was chosen as it is consistent with updating `BelongsToMany` relationships and allows the query string to be mostly static, taking a variable value to control its behaviour. ```graphql mutation UpdatePost($disconnectAuthor: Boolean) { @@ -211,8 +200,7 @@ mutation UpdatePost($disconnectAuthor: Boolean) { } ``` -The `author` relationship will only be disconnected if the value of the variable -`$disconnectAuthor` is `true`, if `false` or `null` are passed, it will not change. +The `author` relationship will only be disconnected if the value of the variable `$disconnectAuthor` is `true`, if `false` or `null` are passed, it will not change. ```json { @@ -261,9 +249,7 @@ mutation UpdatePost($disconnectAuthor: Boolean) { ## MorphTo -The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), -the main difference being that the `connect` operation requires an input type with both -the `id` and `type` of the related model. +The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), the main difference being that the `connect` operation requires an input type with both the `id` and `type` of the related model. ```graphql type Task { @@ -368,8 +354,7 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Phone` model. +This mutation takes a single argument `input` that contains values of the `User` itself and its associated `Phone` model. ```graphql input UpdateUserInput { @@ -435,8 +420,7 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Post` models. +This mutation takes a single argument `input` that contains values of the `User` itself and its associated `Post` models. ```graphql input CreateUserInput { @@ -445,8 +429,7 @@ input CreateUserInput { } ``` -Now, we can expose an operation that allows us to directly create new posts -right when we create the `User`. +Now, we can expose an operation that allows us to directly create new posts right when we create the `User`. ```graphql input CreatePostsHasMany { @@ -562,8 +545,7 @@ mutation { } ``` -The behaviour for `upsert` is a mix between updating and creating, -it will produce the needed action regardless of whether the model exists or not. +The behaviour for `upsert` is a mix between updating and creating, it will produce the needed action regardless of whether the model exists or not. ## MorphMany @@ -571,8 +553,7 @@ Works exactly like [Has Many](#hasmany). ## BelongsToMany -A belongs to many relation allows you to create new related models as well -as attaching existing ones. +A belongs to many relation allows you to create new related models as well as attaching existing ones. ```graphql type Mutation { @@ -601,8 +582,7 @@ input UpsertAuthorInput { } ``` -Just pass the ID of the models you want to associate or their full information -to create a new relation. +Just pass the ID of the models you want to associate or their full information to create a new relation. ```graphql mutation { @@ -650,8 +630,7 @@ Lighthouse will detect the relationship and attach, update or create it. } ``` -It is also possible to use the `sync` operation to ensure only the given IDs -will be contained within the relation. +It is also possible to use the `sync` operation to ensure only the given IDs will be contained within the relation. ```graphql mutation { @@ -682,8 +661,8 @@ input UpdateAuthorBelongsToMany { ### Storing Pivot Data It is common that many-to-many relations store some extra data in pivot tables. -Suppose we want to track what movies a user has seen. In addition to connecting -the two entities, we want to store how well they liked it: +Suppose we want to track what movies a user has seen. +In addition to connecting the two entities, we want to store how well they liked it: ```graphql type User { @@ -702,13 +681,11 @@ type UserMoviePivot { } ``` -Laravel's `sync()`, `syncWithoutDetach()` or `connect()` methods allow you to pass -an array where the keys are IDs of related models and the values are pivot data. +Laravel's `sync()`, `syncWithoutDetach()` or `connect()` methods allow you to pass an array where the keys are IDs of related models and the values are pivot data. Lighthouse exposes this capability through the nested operations on many-to-many relations. Instead of passing just a list of ids, you can define an `input` type that also contains pivot data. -It must contain a field called `id` to contain the ID of the related model, -all other fields will be inserted into the pivot table. +It must contain a field called `id` to contain the ID of the related model, all other fields will be inserted into the pivot table. ```graphql type Mutation { diff --git a/docs/5/eloquent/polymorphic-relationships.md b/docs/5/eloquent/polymorphic-relationships.md index fc8ea0cd5b..ef5de1f768 100644 --- a/docs/5/eloquent/polymorphic-relationships.md +++ b/docs/5/eloquent/polymorphic-relationships.md @@ -27,8 +27,7 @@ type Image { ``` First, let's go ahead and add the relations to `Image` since they are straightforward. -The field name should match your relationship method name and be annotated -with the [@morphOne](../api-reference/directives.md#morphone) directive. +The field name should match your relationship method name and be annotated with the [@morphOne](../api-reference/directives.md#morphone) directive. ```graphql type Post { @@ -44,20 +43,17 @@ type User { } ``` -Depending on the rules of your application, you might require the relationship -to be there in some cases, while allowing it to be absent in others. In this -example, a `Post` must always have an `Image`, while a `User` does not require one. +Depending on the rules of your application, you might require the relationship to be there in some cases, while allowing it to be absent in others. +In this example, a `Post` must always have an `Image`, while a `User` does not require one. -For the inverse, you will need to define a [union type](../the-basics/types.md#union) -to express that an `Image` might be linked to different models. +For the inverse, you will need to define a [union type](../the-basics/types.md#union) to express that an `Image` might be linked to different models. ```graphql union Imageable = Post | User ``` Now, reference the union type from a field in your `Image` type. -You can use the [@morphTo](../api-reference/directives.md#morphto) directive -for performance optimization. +You can use the [@morphTo](../api-reference/directives.md#morphto) directive for performance optimization. ```graphql type Image { @@ -67,8 +63,8 @@ type Image { } ``` -The default type resolver will be able to determine which concrete object type is returned -when dealing with Eloquent models, so your definition should just work. +The default type resolver will be able to determine which concrete object type is returned when dealing with Eloquent models. +Your definition should just work. Given you have a field `images` that returns a list of `[Image!]!`, you could query it like this: @@ -90,10 +86,8 @@ Given you have a field `images` that returns a list of `[Image!]!`, you could qu ## One to Many -Based on the above example, you could change your application to allow -for a `Post` to have many images attached to it. -The field `images` now returns a list of `Image` object and is annotated -with the [@morphMany](../api-reference/directives.md#morphmany) directive. +Based on the above example, you could change your application to allow for a `Post` to have many images attached to it. +The field `images` now returns a list of `Image` object and is annotated with the [@morphMany](../api-reference/directives.md#morphmany) directive. ```graphql type Post { diff --git a/docs/5/eloquent/relationships.md b/docs/5/eloquent/relationships.md index cd9886e964..84763e189b 100644 --- a/docs/5/eloquent/relationships.md +++ b/docs/5/eloquent/relationships.md @@ -34,19 +34,17 @@ type Post { } ``` -Because Laravel relationships can be accessed just like regular properties on your model, -the default field resolver will work just fine. +Because Laravel relationships can be accessed just like regular properties on your model, the default field resolver will work just fine. ## Avoiding the N+1 performance problem When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. -This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: -the so-called N+1 query problem. [Learn more](../performance/n-plus-one.md). +This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: the so-called N+1 query problem. +[Learn more](../performance/n-plus-one.md). -When you decorate your relationship fields with Lighthouse's built-in relationship -directives, queries are automatically combined through a technique called _batch loading_. +When you decorate your relationship fields with Lighthouse's built-in relationship directives, queries are automatically combined through a technique called _batch loading_. That means you get fewer database requests and better performance without doing much work. > Batch loading might not provide ideal performance for all use cases. You can turn @@ -54,8 +52,7 @@ That means you get fewer database requests and better performance without doing ## One To One -Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) -between two types in your schema. +Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) between two types in your schema. ```graphql type User { @@ -91,8 +88,7 @@ type Comment { ## Many To Many -While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) -are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. +While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. Use the [@belongsToMany](../api-reference/directives.md#belongstomany) directive to define it. ```graphql @@ -121,9 +117,8 @@ type Project { ## Renaming relations -When you define a relation, Lighthouse assumes that the field and the relationship -method have the same name. If you need to name your field differently, you have to -specify the name of the method. +When you define a relation, Lighthouse assumes that the field and the relationship method have the same name. +If you need to name your field differently, you have to specify the name of the method. ```graphql type Post { diff --git a/docs/5/eloquent/soft-deleting.md b/docs/5/eloquent/soft-deleting.md index ee4ba35b21..c5610e70b6 100644 --- a/docs/5/eloquent/soft-deleting.md +++ b/docs/5/eloquent/soft-deleting.md @@ -1,13 +1,10 @@ # Soft Deleting -Lighthouse offers convenient helpers to work with models that utilize -[soft deletes](https://laravel.com/docs/eloquent#soft-deleting). +Lighthouse offers convenient helpers to work with models that utilize [soft deletes](https://laravel.com/docs/eloquent#soft-deleting). ## Filter Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field -to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. ```graphql type Query { @@ -15,8 +12,7 @@ type Query { } ``` -Lighthouse will automatically add an argument `trashed` to the field definition -and include the enum `Trashed`. +Lighthouse will automatically add an argument `trashed` to the field definition and include the enum `Trashed`. ```graphql type Query { @@ -45,8 +41,7 @@ You can include soft deleted models in your result with a query like this: ## Restoring Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. ```graphql type Mutation { @@ -68,8 +63,7 @@ This mutation will return the restored object. ## Permanently Deleting Models -To truly remove a model from the database, -use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. +To truly remove a model from the database, use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. Your model must use the `Illuminate\Database\Eloquent\SoftDeletes` trait. ```graphql diff --git a/docs/5/federation/entities.md b/docs/5/federation/entities.md index a8f1e9937c..cd00aa0e2c 100644 --- a/docs/5/federation/entities.md +++ b/docs/5/federation/entities.md @@ -1,13 +1,11 @@ # Entities A core component of a federation capable GraphQL service is the `_entities` field. -For a given `__typename` in the given `$representations`, Lighthouse will look for -a resolver to return the full `_Entity`. +For a given `__typename` in the given `$representations`, Lighthouse will look for a resolver to return the full `_Entity`. ## Class Based Resolvers -Lighthouse will look for a class which name is equivalent to `__typename` in the -namespace configured in `lighthouse.federation.entities_resolver_namespace`. +Lighthouse will look for a class which name is equivalent to `__typename` in the namespace configured in `lighthouse.federation.entities_resolver_namespace`. ```graphql { @@ -22,8 +20,7 @@ namespace configured in `lighthouse.federation.entities_resolver_namespace`. ### Single Entity Resolvers After validating the type `Foo` exists, Lighthouse will look for a resolver class in `App\GraphQL\Entities\Foo`. -The resolver class is expected to contain a method `__invoke()` which takes a single argument: -the array form of the representation. +The resolver class is expected to contain a method `__invoke()` which takes a single argument: the array form of the representation. ```php namespace App\GraphQL\Entities; @@ -42,10 +39,9 @@ class Foo ### Batched Entity Resolves -When the client requests a large number of entities with the same type, it can be more efficient to resolve -them all at once. When your entity resolver class implements `Nuwave\Lighthouse\Federation\BatchedEntityResolver`, -Lighthouse will call it a single time with a list of all representations of its type. The resolver can then do -some kind of batch query to resolve them and return them all at once. +When the client requests a large number of entities with the same type, it can be more efficient to resolve them all at once. +When your entity resolver class implements `Nuwave\Lighthouse\Federation\BatchedEntityResolver`, Lighthouse will call it a single time with a list of all representations of its type. +The resolver can then do some kind of batch query to resolve them and return them all at once. ```php namespace App\GraphQL\Entities; @@ -66,8 +62,7 @@ class Foo implements BatchedEntityResolver ## Eloquent Model Resolvers -When no resolver class can be found, Lighthouse will attempt to find the model that -matches the type `__typename`, using the namespaces configured in `lighthouse.namespaces.models`. +When no resolver class can be found, Lighthouse will attempt to find the model that matches the type `__typename`, using the namespaces configured in `lighthouse.namespaces.models`. ```graphql { @@ -79,8 +74,7 @@ matches the type `__typename`, using the namespaces configured in `lighthouse.na } ``` -The additional fields in the representation constrain the query builder, which is then -called and expected to return a single result. +The additional fields in the representation constrain the query builder, which is then called and expected to return a single result. ```php $results = App\Models\Foo::query() diff --git a/docs/5/federation/getting-started.md b/docs/5/federation/getting-started.md index 005847fe99..06fd666115 100644 --- a/docs/5/federation/getting-started.md +++ b/docs/5/federation/getting-started.md @@ -21,5 +21,4 @@ Add the service provider to your `config/app.php`: ## Extends You have to use `@extends` in place of `extend type` to annotate type references. -This is because Lighthouse merges type extensions before the final schema is produced, -thus they would not be preserved to appear in the federation schema SDL. +This is because Lighthouse merges type extensions before the final schema is produced, thus they would not be preserved to appear in the federation schema SDL. diff --git a/docs/5/getting-started/configuration.md b/docs/5/getting-started/configuration.md index 93abc1f662..8cf02d8efa 100644 --- a/docs/5/getting-started/configuration.md +++ b/docs/5/getting-started/configuration.md @@ -11,9 +11,8 @@ The configuration file will be placed in `config/lighthouse.php`. ## CORS -A GraphQL API can be consumed from multiple clients, which may or may not reside -on the same domain as your server. Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) -for your GraphQL endpoint in `config/cors.php`: +A GraphQL API can be consumed from multiple clients, which may or may not reside on the same domain as your server. +Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) for your GraphQL endpoint in `config/cors.php`: ```diff return [ diff --git a/docs/5/getting-started/installation.md b/docs/5/getting-started/installation.md index 3ef7ae12c5..8b9cd31380 100644 --- a/docs/5/getting-started/installation.md +++ b/docs/5/getting-started/installation.md @@ -10,8 +10,8 @@ composer require nuwave/lighthouse ## Publish the default schema -Lighthouse includes a default schema to get you going right away. Publish -it using the following `artisan` command: +Lighthouse includes a default schema to get you going right away. +Publish it using the following `artisan` command: ```bash php artisan vendor:publish --tag=lighthouse-schema @@ -39,9 +39,8 @@ $app->register(\Nuwave\Lighthouse\LighthouseServiceProvider::class); ``` The many features Lighthouse provides are split across multiple service providers. -Since Lumen does not support auto-discovery, you will have to register them individually -depending on which features you want to use. Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), -the section `extra.laravel.providers` contains the default service providers. +Since Lumen does not support auto-discovery, you will have to register them individually depending on which features you want to use. +Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), the section `extra.laravel.providers` contains the default service providers. To get you going right away in Lumen, copy over the included default schema. It uses pagination and validation, so you need to register the service providers. @@ -59,8 +58,7 @@ $app->register(\Nuwave\Lighthouse\Validation\ValidationServiceProvider::class); ## IDE Support Lighthouse makes heavy use of the SDL and utilizes schema directives. -To improve your editing experience, you can generate a definition file -[with an artisan command](../api-reference/commands.md#ide-helper): +To improve your editing experience, you can generate a definition file [with an artisan command](../api-reference/commands.md#ide-helper): ```bash php artisan lighthouse:ide-helper @@ -70,8 +68,7 @@ For Phpstorm, we recommend [the GraphQL plugin](https://plugins.jetbrains.com/pl ## Install GraphQL DevTools -To make use of the amazing tooling around GraphQL, we recommend -installing [GraphiQL](https://github.com/mll-lab/laravel-graphiql). +To make use of the amazing tooling around GraphQL, we recommend installing [GraphiQL](https://github.com/mll-lab/laravel-graphiql). ```bash composer require mll-lab/laravel-graphiql @@ -79,5 +76,5 @@ composer require mll-lab/laravel-graphiql After installation, visit `/graphiql` to try it. -You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in -the config. By default, the endpoint lives at `/graphql`. +You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in the config. +By default, the endpoint lives at `/graphql`. diff --git a/docs/5/getting-started/migrating-to-lighthouse.md b/docs/5/getting-started/migrating-to-lighthouse.md index f1e0514e0d..531660db6a 100644 --- a/docs/5/getting-started/migrating-to-lighthouse.md +++ b/docs/5/getting-started/migrating-to-lighthouse.md @@ -1,15 +1,12 @@ # Migrating to Lighthouse -This section contains advice on how you can migrate existing -API projects to Lighthouse. +This section contains advice on how you can migrate existing API projects to Lighthouse. ## Schema definition -The most important thing to get you started using Lighthouse will -be a schema that is written using GraphQL Schema Definition Language. +The most important thing to get you started using Lighthouse will be a schema that is written using GraphQL Schema Definition Language. -If you already have a server with another library up and running, you -can use introspection to retrieve this schema and save it to a file. +If you already have a server with another library up and running, you can use introspection to retrieve this schema and save it to a file. A simple tool that is also generally useful is [graphql-cli](https://github.com/graphql-cli/graphql-cli). @@ -17,23 +14,18 @@ A simple tool that is also generally useful is [graphql-cli](https://github.com/ graphql init graphql get-schema --endpoint=example.com/graphql --output=schema.graphql -Type definitions that previously done through code can mostly be deduced from -the schema. Sometimes, additional annotations or a PHP implementation is required. +Type definitions that previously done through code can mostly be deduced from the schema. +Sometimes, additional annotations or a PHP implementation is required. [How to define types](../the-basics/types.md) ## Resolver logic -If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), -[rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that -is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), -you should be able to reuse much of your existing code. +If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), [rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), you should be able to reuse much of your existing code. -You can also register your existing types within Lighthouse's type registry, so you -won't have to rewrite them in SDL: [Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). +You can also register your existing types within Lighthouse's type registry, so you won't have to rewrite them in SDL. +[Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). -Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature), -so you should be able to reuse any logic you have written for Queries/Mutations. +Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature). +You should be able to reuse any logic you have written for Queries/Mutations. -Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), -[eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), -[pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). +Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), [eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), [pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). diff --git a/docs/5/performance/caching.md b/docs/5/performance/caching.md index a4630ba53d..2f455e5c6c 100644 --- a/docs/5/performance/caching.md +++ b/docs/5/performance/caching.md @@ -1,8 +1,7 @@ # Caching -If some fields in your schema are expensive or slow to compute, it can be -beneficial to cache their result. Use the [@cache](../api-reference/directives.md#cache) -directive to instruct Lighthouse to cache the result of a resolver. +If some fields in your schema are expensive or slow to compute, it can be beneficial to cache their result. +Use the [@cache](../api-reference/directives.md#cache) directive to instruct Lighthouse to cache the result of a resolver. The cache is created on the first request and is cached forever by default. Use this for values that seldom change and take long to fetch/compute. @@ -32,8 +31,7 @@ type Query { ## Clear cache -To enable this feature, you need to use a cache store that supports [cache tags](https://laravel.com/docs/cache#cache-tags) -and enable cache tags in `config/lighthouse.php`: +To enable this feature, you need to use a cache store that supports [cache tags](https://laravel.com/docs/cache#cache-tags) and enable cache tags in `config/lighthouse.php`: ```php 'cache' => [ @@ -44,9 +42,9 @@ and enable cache tags in `config/lighthouse.php`: ], ``` -Now, you can place the [@clearCache](../api-reference/directives.md#clearcache) directive on -mutation fields. When they are queried, they will invalidate all cache entries associated with -a calculated tag. Depending on the effect of the mutation, you can clear different tags. +Now, you can place the [@clearCache](../api-reference/directives.md#clearcache) directive on mutation fields. +When they are queried, they will invalidate all cache entries associated with a calculated tag. +Depending on the effect of the mutation, you can clear different tags. Update the cache associated with a given type without a specific ID: @@ -90,8 +88,7 @@ If your mutation affects multiple levels of cache, you can apply this directive ## Cache key When generating a cached result for a resolver, Lighthouse produces a unique key for each type. -By default, Lighthouse will look for a field of type `ID` on the parent to generate the key -for a field with [@cache](../api-reference/directives.md#cache). +By default, Lighthouse will look for a field of type `ID` on the parent to generate the key for a field with [@cache](../api-reference/directives.md#cache). This directive allows to use a different field (i.e., an external API id): @@ -104,15 +101,13 @@ type GithubProfile { ## Implementing your own cache key generator -In one of your application service providers, bind the [`Nuwave\Lighthouse\Cache\CacheKeyAndTags.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTags.php) -interface to your cache key generator class: +In one of your application service providers, bind the [`Nuwave\Lighthouse\Cache\CacheKeyAndTags.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTags.php) interface to your cache key generator class: ```php $this->app->bind(CacheKeyAndTags::class, YourOwnCacheKeyGenerator::class); ``` -You can extend [`Nuwave\Lighthouse\Cache\CacheKeyAndTagsGenerator.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTagsGenerator.php) -to override certain methods, or implement the interface from scratch. +You can extend [`Nuwave\Lighthouse\Cache\CacheKeyAndTagsGenerator.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTagsGenerator.php) to override certain methods, or implement the interface from scratch. ## HTTP Cache-Control header @@ -126,9 +121,7 @@ Add the service provider to your `config/app.php`: ], ``` -You can change the [`Cache-Control` header](https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control) of your response -regardless of [@cache](../api-reference/directives.md#cache) -by adding the [@cacheControl](../api-reference/directives.md#cachecontrol) directive to a field. +You can change the [`Cache-Control` header](https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control) of your response regardless of [@cache](../api-reference/directives.md#cache) by adding the [@cacheControl](../api-reference/directives.md#cachecontrol) directive to a field. The final header settings are calculated based on these rules: diff --git a/docs/5/performance/deferred.md b/docs/5/performance/deferred.md index f34093f134..dd4ae7feb1 100644 --- a/docs/5/performance/deferred.md +++ b/docs/5/performance/deferred.md @@ -7,8 +7,8 @@ Currently the `@defer` directive requires Apollo Client in alpha. Track the state of the PR here: https://github.com/apollographql/apollo-client/pull/3686#issuecomment-555534519 ::: -Deferring fields allows you to prioritize fetching data needed to render the most important content -as fast as possible, and then loading the rest of the page in the background. +Deferring fields allows you to prioritize fetching data needed to render the most important content as fast as possible, +and then loading the rest of the page in the background. Lighthouse adds support for the experimental `@defer` directive through an extension. Read more about it [here](https://www.apollographql.com/blog/introducing-defer-in-apollo-server-f6797c4e9d6e). @@ -25,10 +25,8 @@ Add the service provider to your `config/app.php`: ## Configuration -Consider the configuration options in your `config/lighthouse.php` to prevent -deferred queries from running to long. +Consider the configuration options in your `config/lighthouse.php` to prevent deferred queries from running to long.
-![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) -_(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ +![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) _(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ diff --git a/docs/5/performance/n-plus-one.md b/docs/5/performance/n-plus-one.md index ca0118b8e6..9d22777597 100644 --- a/docs/5/performance/n-plus-one.md +++ b/docs/5/performance/n-plus-one.md @@ -1,10 +1,8 @@ # The N+1 Query Problem -A common performance pitfall that comes with the nested nature of GraphQL queries -is the so-called N+1 query problem. +A common performance pitfall that comes with the nested nature of GraphQL queries is the so-called N+1 query problem. -Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the -name of the associated author: +Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the name of the associated author: ```graphql { @@ -17,19 +15,14 @@ name of the associated author: } ``` -Following a naive execution strategy, Lighthouse would first query a list of posts, -then loop over that list and resolve the individual fields. -The associated author for each post would be lazily loaded, querying the database -once per post. +Following a naive execution strategy, Lighthouse would first query a list of posts, then loop over that list and resolve the individual fields. +The associated author for each post would be lazily loaded, querying the database once per post. ## Eager Loading Relationships -When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) -is commonly used to alleviate the N+1 query problem. +When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) is commonly used to alleviate the N+1 query problem. -You can leverage eager loading by informing Lighthouse of the relationships between your models, -using directives such as [@belongsTo](../api-reference/directives.md#belongsto), [@hasMany](../api-reference/directives.md#hasmany) -and [@with](../api-reference/directives.md#with). +You can leverage eager loading by informing Lighthouse of the relationships between your models, using directives such as [@belongsTo](../api-reference/directives.md#belongsto), [@hasMany](../api-reference/directives.md#hasmany) and [@with](../api-reference/directives.md#with). ```graphql type Post { @@ -45,13 +38,12 @@ type User { Under the hood, Lighthouse will batch the relationship queries together in a single database query. -If you require a relation to be loaded for some field, but do not wish to return the relationship itself, -you can use the [@with](../api-reference/directives.md#with) directive. +If you require a relation to be loaded for some field. +Do not wish to return the relationship itself, you can use the [@with](../api-reference/directives.md#with) directive. ## Custom Batch Loaders -In the following example, the `User` model is associated with multiple posts, but the posts -are part of an external service. +In the following example, the `User` model is associated with multiple posts, but the posts are part of an external service. ```graphql type User { @@ -76,20 +68,18 @@ Since we have multiple users, `User.posts` would be resolved multiple times in t } ``` -We want to have a batch loader for `User.posts`, since it loads posts from a third party and the -call to fetch them is slow when run sequentially. This is assuming the posts service offers a method -to query posts for multiple users in one call. +We want to have a batch loader for `User.posts`, since it loads posts from a third party and the call to fetch them is slow when run sequentially. +This is assuming the posts service offers a method to query posts for multiple users in one call. -In order for Lighthouse to perform batch loading, it needs to group fields that are on the same level -in the query tree, but nested under different indices. When looking at the query path from `posts`, they may look like: +In order for Lighthouse to perform batch loading, it needs to group fields that are on the same level in the query tree, but nested under different indices. +When looking at the query path from `posts`, they may look like: - `users.0.posts` - `users.1.posts` In order to combine them, you need to have a single stateful batch loader instance for `users.posts`. Use `Nuwave\Lighthouse\Execution\BatchLoader\BatchLoaderRegistry` to resolve such instances. -The following code is the resolver for `User.posts` - it could point to it with [@field](../api-reference/directives.md#field), -or be implemented in a custom directive. +The following code is the resolver for `User.posts` - it could point to it with [@field](../api-reference/directives.md#field), or be implemented in a custom directive. ```php use GraphQL\Deferred; @@ -109,8 +99,7 @@ function (User $user, array $args, GraphQLContext $context, ResolveInfo $resolve } ``` -The implementation of `UserPostsBatchLoader` is up to you, the only important thing is that the resolver -returns an instance of `GraphQL\Deferred`, see [webonyx/graphql-php docs](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). +The implementation of `UserPostsBatchLoader` is up to you, the only important thing is that the resolver returns an instance of `GraphQL\Deferred`, see [webonyx/graphql-php docs](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). The following example illustrates some common patterns that may be found in a batch loader implementation: ```php diff --git a/docs/5/performance/query-caching.md b/docs/5/performance/query-caching.md index 2af2f17152..f896a79a13 100644 --- a/docs/5/performance/query-caching.md +++ b/docs/5/performance/query-caching.md @@ -2,7 +2,8 @@ In order to speed up GraphQL query parsing, the parsed queries can be stored in the Laravel cache. -Query caching is enabled by default. You can define cache store and cache duration, see `config/lighthouse.php`. +Query caching is enabled by default. +You can define cache store and cache duration, see `config/lighthouse.php`. Make sure you flush the query cache when you deploy an upgraded version of the `webonyx/graphql-php` dependency: @@ -10,8 +11,7 @@ Make sure you flush the query cache when you deploy an upgraded version of the ` ## Automated Persisted Queries -Lighthouse supports Automatic Persisted Queries (APQ), compatible with the -[Apollo implementation](https://www.apollographql.com/docs/apollo-server/performance/apq). +Lighthouse supports Automatic Persisted Queries (APQ), compatible with the [Apollo implementation](https://www.apollographql.com/docs/apollo-server/performance/apq). APQ is enabled by default, but depends on query caching being enabled. diff --git a/docs/5/performance/schema-caching.md b/docs/5/performance/schema-caching.md index 38d30c12a0..1dae4ffba1 100644 --- a/docs/5/performance/schema-caching.md +++ b/docs/5/performance/schema-caching.md @@ -1,20 +1,18 @@ # Schema caching -As your schema grows larger, the construction of the schema from raw `.graphql` files -becomes more and more costly. +As your schema grows larger, the construction of the schema from raw `.graphql` files becomes more and more costly. Schema caching is enabled in non-local environments by default, see `config/lighthouse.php`. ## Deployment -Update your cache when deploying a new version of your application -using the [cache](../api-reference/commands.md#cache) artisan command: +Update your cache when deploying a new version of your application using the [cache](../api-reference/commands.md#cache) artisan command: php artisan lighthouse:cache The structure of the serialized schema can change between Lighthouse releases. -In order to prevent errors, use cache version 2 and a deployment method that -atomically updates both the cache file and the dependencies, e.g. K8s. +In order to prevent errors, use cache version 2 and a deployment method that atomically updates both the cache file and the dependencies, e.g. +K8s. ## Development diff --git a/docs/5/performance/server-configuration.md b/docs/5/performance/server-configuration.md index 9339ebf235..561c14b335 100644 --- a/docs/5/performance/server-configuration.md +++ b/docs/5/performance/server-configuration.md @@ -9,5 +9,4 @@ If you have the freedom to install it on your server, it's an easy way to get a ## Xdebug -Enabling Xdebug and having an active debug session slows down execution by -an order of magnitude. +Enabling Xdebug and having an active debug session slows down execution by an order of magnitude. diff --git a/docs/5/security/authentication.md b/docs/5/security/authentication.md index 3e7332caff..96d5538b59 100644 --- a/docs/5/security/authentication.md +++ b/docs/5/security/authentication.md @@ -1,16 +1,13 @@ # Authentication -You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) -to authenticate users of your GraphQL API. +You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) to authenticate users of your GraphQL API. ## AttemptAuthentication middleware -As all GraphQL requests are served at a single HTTP endpoint, middleware added -through the `lighthouse.php` config will run for all queries against your server. +As all GraphQL requests are served at a single HTTP endpoint, middleware added through the `lighthouse.php` config will run for all queries against your server. -In most cases, your schema will have some publicly accessible fields and others -that require authentication. As multiple checks for authentication or permissions may be -required in a single request, it is convenient to attempt authentication once per request. +In most cases, your schema will have some publicly accessible fields and others that require authentication. +As multiple checks for authentication or permissions may be required in a single request, it is convenient to attempt authentication once per request. ```php 'route' => [ @@ -20,12 +17,10 @@ required in a single request, it is convenient to attempt authentication once pe ], ``` -Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated -access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. +Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. -If you want to guard all your fields against unauthenticated access, you can simply add -Laravel's build-in auth middleware. Beware that this approach does not allow any GraphQL -operations for guest users, so you will have to handle login outside of GraphQL. +If you want to guard all your fields against unauthenticated access, you can simply add Laravel's build-in auth middleware. +Beware that this approach does not allow any GraphQL operations for guest users, so you will have to handle login outside of GraphQL. ```php 'middleware' => [ @@ -41,15 +36,13 @@ You can configure a default guard to use for authenticating GraphQL requests in 'guard' => 'api', ``` -This setting is used whenever Lighthouse looks for an authenticated user, for example in directives -such as [@guard](../api-reference/directives.md#guard), or when applying the `AttemptAuthentication` middleware. +This setting is used whenever Lighthouse looks for an authenticated user, for example in directives such as [@guard](../api-reference/directives.md#guard), or when applying the `AttemptAuthentication` middleware. Stateless guards are recommended for most use cases, such as the default `api` guard. ### Laravel Sanctum -If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard -to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the first middleware for Lighthouse's route. +If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the first middleware for Lighthouse's route. ```php 'route' => [ @@ -63,11 +56,9 @@ to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the f 'guard' => 'sanctum', ``` -Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) -with all GraphQL requests, regardless of whether the user is authenticated or not. +Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) with all GraphQL requests, regardless of whether the user is authenticated or not. -When using [mll-lab/laravel-graphiql](https://github.com/mll-lab/laravel-graphiql), follow the [instructions -to add a CSRF token](https://github.com/mll-lab/laravel-graphiql#configure-session-authentication). +When using [mll-lab/laravel-graphiql](https://github.com/mll-lab/laravel-graphiql), follow the [instructions to add a CSRF token](https://github.com/mll-lab/laravel-graphiql#configure-session-authentication). ## Guard selected fields @@ -79,8 +70,8 @@ type Query { } ``` -If you need to guard multiple fields, use [@guard](../api-reference/directives.md#guard) -on a `type` or an `extend type` definition. It will be applied to all fields within that type. +If you need to guard multiple fields, use [@guard](../api-reference/directives.md#guard) on a `type` or an `extend type` definition. +It will be applied to all fields within that type. ```graphql extend type Query @guard { @@ -89,8 +80,7 @@ extend type Query @guard { } ``` -The `@guard` directive will be prepended to other directives defined on the fields -and thus executes before them. +The `@guard` directive will be prepended to other directives defined on the fields and thus executes before them. ```graphql extend type Query { @@ -112,8 +102,7 @@ type Query { } ``` -Sending the following query will return the authenticated user's info -or `null` if the request is not authenticated. +Sending the following query will return the authenticated user's info or `null` if the request is not authenticated. ```graphql { @@ -126,9 +115,7 @@ or `null` if the request is not authenticated. ## Stateful Authentication Example -You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). -**This only works when Lighthouse's guard uses a session driver.** -Laravel's token based authentication does not allow logging in or out on the server side. +You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). **This only works when Lighthouse's guard uses a session driver.** Laravel's token based authentication does not allow logging in or out on the server side. The implementation in the docs is only an example and may have to be adapted to your specific use case. diff --git a/docs/5/security/authorization.md b/docs/5/security/authorization.md index c7859adcd3..969e7abaef 100644 --- a/docs/5/security/authorization.md +++ b/docs/5/security/authorization.md @@ -3,8 +3,7 @@ Not every user in your application may be allowed to see all data or do any action. You can control what they can do by enforcing authorization rules. -Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's -a prerequisite to have your users logged in before checking what they can do. +Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's a prerequisite to have your users logged in before checking what they can do. ## Utilize the Viewer pattern @@ -39,8 +38,7 @@ type Note { } ``` -Now, authenticated users can query for items that belong to them and are naturally -limited to seeing just those. +Now, authenticated users can query for items that belong to them and are naturally limited to seeing just those. ```graphql { @@ -57,8 +55,7 @@ limited to seeing just those. ## Restrict fields through policies Lighthouse allows you to restrict field operations to a certain group of users. -Use the [@can](../api-reference/directives.md#can) directive -to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. +Use the [@can](../api-reference/directives.md#can) directive to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. Starting from Laravel 5.7, [authorization of guest users](https://laravel.com/docs/authorization#guest-users) is supported. Because of this, Lighthouse does **not** validate that the user is authenticated before passing it along to the policy. @@ -89,8 +86,7 @@ class PostPolicy ### Protect specific model instances For some models, you may want to restrict access for specific instances of a model. -Set the `resolved` argument to `true` to have Lighthouse check permissions against -the resolved model instances. +Set the `resolved` argument to `true` to have Lighthouse check permissions against the resolved model instances. > This will actually run the field before checking permissions, do not use in mutations. @@ -134,8 +130,7 @@ class PostPolicy } ``` -You can pass along the client given input data as arguments to the policy checks -with the `injectArgs` argument: +You can pass along the client given input data as arguments to the policy checks with the `injectArgs` argument: ```graphql type Mutation { @@ -153,8 +148,7 @@ class PostPolicy } ``` -When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as -the second parameter and the static `args` as the third parameter: +When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as the second parameter and the static `args` as the third parameter: ```php class PostPolicy @@ -165,15 +159,12 @@ class PostPolicy ## Custom field restrictions -For applications with role management, it is common to hide some model attributes from a -certain group of users. At the moment, Laravel and Lighthouse offer no canonical solution -for this. +For applications with role management, it is common to hide some model attributes from a certain group of users. +At the moment, Laravel and Lighthouse offer no canonical solution for this. -A great way to implement something that fits your use case is to create -[a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). +A great way to implement something that fits your use case is to create [a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). Field middleware allows you to intercept field access and conditionally hide them. -You can hide a field by returning `null` instead of calling the final resolver, or maybe even -abort execution by throwing an error. +You can hide a field by returning `null` instead of calling the final resolver, or maybe even abort execution by throwing an error. The following directive `@canAccess` is an example implementation, make sure to adapt it to your needs. It assumes a simple role system where a `User` has a single attribute `$role`. diff --git a/docs/5/security/csrf.md b/docs/5/security/csrf.md index 112772f043..5b91b3130f 100644 --- a/docs/5/security/csrf.md +++ b/docs/5/security/csrf.md @@ -2,8 +2,8 @@ To learn about cross-site request forgeries, see [Laravel docs](https://laravel.com/docs/csrf). -Lighthouse provides mitigation against CSRF attacks through the `Nuwave\Lighthouse\Support\Http\Middleware\EnsureXHR` -middleware. Just add it as the first middleware for the Lighthouse route in `config/lighthouse.php`: +Lighthouse provides mitigation against CSRF attacks through the `Nuwave\Lighthouse\Support\Http\Middleware\EnsureXHR` middleware. +Just add it as the first middleware for the Lighthouse route in `config/lighthouse.php`: ```php 'route' => [ diff --git a/docs/5/security/resource-exhaustion.md b/docs/5/security/resource-exhaustion.md index bc85472538..623da7058a 100644 --- a/docs/5/security/resource-exhaustion.md +++ b/docs/5/security/resource-exhaustion.md @@ -3,9 +3,8 @@ GraphQL gives enormous power to clients. With great power there must also come great responsibility đŸ•·. -Since clients have the possibility to craft very complex queries, we must be ready -to handle them properly. These queries may be abusive queries from evil clients, -or may simply be very large queries used by legitimate clients. +Since clients have the possibility to craft very complex queries, we must be ready to handle them properly. +These queries may be abusive queries from evil clients, or may simply be very large queries used by legitimate clients. In both of these cases, the client can potentially take your GraphQL server down. _This intro was taken from HowToGraphQL, we recommend reading their full chapter on security https://www.howtographql.com/advanced/4-security/_ diff --git a/docs/5/security/sanitization.md b/docs/5/security/sanitization.md index 0b0b0a765b..92bb6a9adf 100644 --- a/docs/5/security/sanitization.md +++ b/docs/5/security/sanitization.md @@ -1,16 +1,14 @@ # Sanitization When dealing with user input, you need to make sure the given data is valid. -While [validation](validation) is a great first line of defense, there are cases where -it is most practical to modify the given input to ensure it is valid or safe to use. +While [validation](validation) is a great first line of defense, there are cases where it is most practical to modify the given input to ensure it is valid or safe to use. ## Single arguments A great way to deal with single values is to use an [`ArgTransformerDirective`](../custom-directives/argument-directives.md#argtransformerdirective). Lighthouse offers a few built-in options, but it is also really easy to build your own. -Here is how you can remove whitespace of a given input string by using -the built-in [@trim](../api-reference/directives.md#trim) directive: +Here is how you can remove whitespace of a given input string by using the built-in [@trim](../api-reference/directives.md#trim) directive: ```graphql type Mutation { @@ -20,6 +18,4 @@ type Mutation { ## Complex arguments -When you need to look at multiple input fields in order to run sanitization, you can use -a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) -to transform the given inputs before passing them along to the final resolver. +When you need to look at multiple input fields in order to run sanitization, you can use a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) to transform the given inputs before passing them along to the final resolver. diff --git a/docs/5/security/validation.md b/docs/5/security/validation.md index a6758da193..220344d308 100644 --- a/docs/5/security/validation.md +++ b/docs/5/security/validation.md @@ -1,12 +1,10 @@ # Validation -Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) -for your queries and mutations. +Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) for your queries and mutations. ## Single Arguments -The simplest way to leverage the built-in validation rules is to use the -[@rules](../api-reference/directives.md#rules) directive. +The simplest way to leverage the built-in validation rules is to use the [@rules](../api-reference/directives.md#rules) directive. ```graphql type Mutation { @@ -14,8 +12,7 @@ type Mutation { } ``` -In the case of a validation error, Lighthouse will abort execution and return the validation messages -as part of the response. +In the case of a validation error, Lighthouse will abort execution and return the validation messages as part of the response. ```graphql mutation { @@ -96,11 +93,9 @@ input CreatePostInput { } ``` -Using the [`unique`](https://laravel.com/docs/validation#rule-unique) -validation rule can be a bit tricky. +Using the [`unique`](https://laravel.com/docs/validation#rule-unique) validation rule can be a bit tricky. -If the argument is nested within an input object, the argument path will not -match the column name, so you have to specify the column name explicitly. +If the argument is nested within an input object, the argument path will not match the column name, so you have to specify the column name explicitly. ```graphql input CreateUserInput { @@ -110,8 +105,7 @@ input CreateUserInput { ## Validating Arrays -When you are passing in an array as an argument to a field, you might -want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) +When you are passing in an array as an argument to a field, you might want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) ```graphql type Mutation { @@ -122,8 +116,7 @@ type Mutation { } ``` -You can also combine this with [@rules](../api-reference/directives.md#rules) to validate -both size and contents of an argument array. +You can also combine this with [@rules](../api-reference/directives.md#rules) to validate both size and contents of an argument array. For example, you might require a list of at least 3 valid emails to be passed. ```graphql @@ -136,9 +129,9 @@ type Mutation { ## Validator Classes -In cases where your validation becomes too complex and demanding, you want to have the power of PHP to perform -complex validation. For example, accessing existing data in the database or validating the combination of input -values cannot be achieved with the examples above. This is where validator classes come into play. +In cases where your validation becomes too complex and demanding, you want to have the power of PHP to perform complex validation. +For example, accessing existing data in the database or validating the combination of input values cannot be achieved with the examples above. +This is where validator classes come into play. Validator classes can be reused on field definitions or input types within your schema. Use the [@validator](../api-reference/directives.md#validator) directive: @@ -150,13 +143,13 @@ input UpdateUserInput @validator { } ``` -We need to back that with a validator class. Lighthouse uses a simple naming convention for validator classes, -just use the name of the input type and append `Validator`: +We need to back that with a validator class. +Lighthouse uses a simple naming convention for validator classes, just use the name of the input type and append `Validator`: php artisan lighthouse:validator UpdateUserInputValidator -The resulting class will be placed in your configured validator namespace. Let's go ahead -and define the validation rules for the input: +The resulting class will be placed in your configured validator namespace. +Let's go ahead and define the validation rules for the input: ```php namespace App\GraphQL\Validators; @@ -181,8 +174,8 @@ class UpdateUserInputValidator extends Validator } ``` -Note that this gives you access to all kinds of programmatic validation rules that Laravel -provides. This can give you additional flexibility when you need it. +Note that this gives you access to all kinds of programmatic validation rules that Laravel provides. +This can give you additional flexibility when you need it. ### Custom Validator Messages @@ -207,13 +200,13 @@ type Mutation { } ``` -In that case, Lighthouse will look for a validator class in a sub-namespace matching the parent type, in this case -that would be `Mutation`, so the default FQCN would be `App\GraphQL\Validators\Mutation\UpdateUserValidator`. +In that case, Lighthouse will look for a validator class in a sub-namespace matching the parent type, in this case that would be `Mutation`. +The default FQCN would be `App\GraphQL\Validators\Mutation\UpdateUserValidator`. ### Validator For Nested Inputs -Use multiple validators for complex inputs that include nested input objects. This ensures -they do not grow too complex and can be composed freely. +Use multiple validators for complex inputs that include nested input objects. +This ensures they do not grow too complex and can be composed freely. ## Caveats @@ -239,8 +232,8 @@ input FooInput { } ``` -The following mutation would pass validation, because `notBar` references the `bar` field of `FooInput` -and thus its value `1` is compared to the value `2` - which is different: +The following mutation would pass validation. +`notBar` references the `bar` field of `FooInput` and thus its value `1` is compared to the value `2` - which is different: ```graphql mutation { @@ -250,8 +243,7 @@ mutation { ### Custom Rules With References -When creating custom validation rules with references, you need to tell Lighthouse -which parameters are references, so it can add the full argument path: +When creating custom validation rules with references, you need to tell Lighthouse which parameters are references, so it can add the full argument path: ```graphql input FooInput { @@ -260,8 +252,7 @@ input FooInput { } ``` -In this example, `equal_field` is a custom rule that checks if the argument -is the same as the one referenced by the parameter. +In this example, `equal_field` is a custom rule that checks if the argument is the same as the one referenced by the parameter. The parameters to `with_reference` are: @@ -275,8 +266,7 @@ Lighthouse will call this method with the argument path leading up to the valida ### Comparisons -If you need to validate the size of an integer, you need to add the -`integer` validation rule before: +If you need to validate the size of an integer, you need to add the `integer` validation rule before: ```graphql type Mutation { @@ -285,8 +275,7 @@ type Mutation { ``` Rules that reference other fields work strictly function as such. -For example, it is not possible to use `gt` to compare against a literal value, -use `min` instead: +For example, it is not possible to use `gt` to compare against a literal value, use `min` instead: ```graphql type Mutation { @@ -302,8 +291,7 @@ type Mutation { By default, Lighthouse enables all default query validation rules from `webonyx/graphql-php`. This covers fundamental checks, e.g. queried fields match the schema, variables have values of the correct type. -If you want to add custom rules or change which ones are used, you can bind a custom implementation -of the interface `\Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules` through a service provider. +If you want to add custom rules or change which ones are used, you can bind a custom implementation of the interface `\Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules` through a service provider. ```php use Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules; diff --git a/docs/5/subscriptions/client-implementations.md b/docs/5/subscriptions/client-implementations.md index 5e96148250..61c428e411 100644 --- a/docs/5/subscriptions/client-implementations.md +++ b/docs/5/subscriptions/client-implementations.md @@ -1,12 +1,10 @@ # Client Implementations -To get you up and running quickly, the following sections show how to use subscriptions -with common GraphQL client libraries. +To get you up and running quickly, the following sections show how to use subscriptions with common GraphQL client libraries. ## Apollo for Pusher -To use Lighthouse Pusher subscriptions with the [Apollo](https://www.apollographql.com/docs/react) -client library you will need to create an `apollo-link`: +To use Lighthouse Pusher subscriptions with the [Apollo](https://www.apollographql.com/docs/react) client library you will need to create an `apollo-link`: ```js import { ApolloLink, Observable } from "apollo-link"; @@ -134,13 +132,11 @@ const link = ApolloLink.from([pusherLink, httpLink(`${API_LOCATION}/graphql`)]); ## Apollo for Laravel Echo -If you are using the Laravel Echo subscription driver with Apollo -you can use [this apollo link](https://github.com/thekonz/apollo-lighthouse-subscription-link). +If you are using the Laravel Echo subscription driver with Apollo you can use [this apollo link](https://github.com/thekonz/apollo-lighthouse-subscription-link). ## Relay Modern -To use Lighthouse's Pusher subscriptions with Relay Modern you will -need to create a custom handler and inject it into Relay's environment. +To use Lighthouse's Pusher subscriptions with Relay Modern you will need to create a custom handler and inject it into Relay's environment. ```js import Pusher from "pusher-js"; @@ -245,8 +241,7 @@ export const environment = new Environment({ ## Flutter/Dart -To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will -need to create a custom link below: +To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will need to create a custom link below: ````dart import 'dart:async'; diff --git a/docs/5/subscriptions/defining-fields.md b/docs/5/subscriptions/defining-fields.md index 77a36a3ddb..1cfdb5c412 100644 --- a/docs/5/subscriptions/defining-fields.md +++ b/docs/5/subscriptions/defining-fields.md @@ -12,13 +12,10 @@ The quickest way to define such a field is through the `artisan` generator comma php artisan lighthouse:subscription PostUpdated -Lighthouse will look for a class with the capitalized name of the field that -is defined within the default subscription namespace. -For example, the field `postUpdated` should have a corresponding class at -`App\GraphQL\Subscriptions\PostUpdated`. +Lighthouse will look for a class with the capitalized name of the field that is defined within the default subscription namespace. +For example, the field `postUpdated` should have a corresponding class at `App\GraphQL\Subscriptions\PostUpdated`. -All subscription field classes **must** implement the abstract class -`Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` and implement two methods: +All subscription field classes **must** implement the abstract class `Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` and implement two methods. `authorize` and `filter`. ```php @@ -114,6 +111,4 @@ class PostUpdated extends GraphQLSubscription } ``` -If the default namespaces are not working with your application structure -or you want to be more explicit, you can use the [@subscription](../api-reference/directives.md#subscription) -directive to point to a different class. +If the default namespaces are not working with your application structure or you want to be more explicit, you can use the [@subscription](../api-reference/directives.md#subscription) directive to point to a different class. diff --git a/docs/5/subscriptions/filtering-subscriptions.md b/docs/5/subscriptions/filtering-subscriptions.md index fdccd33774..4a46f386ed 100644 --- a/docs/5/subscriptions/filtering-subscriptions.md +++ b/docs/5/subscriptions/filtering-subscriptions.md @@ -1,6 +1,8 @@ # Filtering Subscriptions -There are times when you'll need to filter out specific events based on the arguments provided by the client. To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. For instance, using the following example: +There are times when you'll need to filter out specific events based on the arguments provided by the client. +To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. +For instance, using the following example: ```graphql subscription onPostUpdated($post_id: ID!) { diff --git a/docs/5/subscriptions/getting-started.md b/docs/5/subscriptions/getting-started.md index 8e859e9f7d..17f0193092 100644 --- a/docs/5/subscriptions/getting-started.md +++ b/docs/5/subscriptions/getting-started.md @@ -1,7 +1,6 @@ # Subscriptions: Getting Started -Subscriptions allow GraphQL clients to observe specific events -and receive updates from the server when those events occur. +Subscriptions allow GraphQL clients to observe specific events and receive updates from the server when those events occur. ::: tip NOTE Much of the credit should be given to the [Ruby implementation](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/overview.md) as they provided a great overview of how the backend should work. @@ -28,8 +27,8 @@ If you want to use the Laravel Echo driver, you need to set the env `LIGHTHOUSE_ Lighthouse returns the subscription channel as part of the response under `extensions`. You can configure which format is used with `subscriptions.version` in `lighthouse.php`. -For new applications, version 2 is recommended. When upgrading, make sure -your clients no longer depend on the redundant `channels` key from version 1. +For new applications, version 2 is recommended. +When upgrading, make sure your clients no longer depend on the redundant `channels` key from version 1. **Version 2 (Recommended)** @@ -65,17 +64,17 @@ your clients no longer depend on the redundant `channels` key from version 1. ### Empty Response Optimization Lighthouse returns the subscription channel as part of the response under `extensions`. -If `subscriptions.exclude_empty` in `lighthouse.php` is set to `true`, -API responses without a subscription channel will not contain `lighthouse_subscriptions` in `extensions`. -This optimizes performance by sending less data, but clients must anticipate this appropriately. +If `subscriptions.exclude_empty` in `lighthouse.php` is set to `true`, API responses without a subscription channel will not contain `lighthouse_subscriptions` in `extensions`. +This optimizes performance by sending less data, +but clients must anticipate this appropriately. ## Expiring Subscriptions Subscriptions do not expire by themselves. Unless you delete a subscription, it will continue to broadcast events after the client has disconnected. -The easiest way to expire subscriptions automatically is to use the env `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL` -to set an expiration time in seconds (e.g. `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL=3600` to expire in one hour). +The easiest way to expire subscriptions automatically is to use the env `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL` to set an expiration time in seconds (e.g. +`LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL=3600` to expire in one hour). ### Pusher Expiration Webhook @@ -89,4 +88,5 @@ The webhook URL will typically be: /graphql/subscriptions/webhook ``` -You can add the webhook in the Pusher Dashboard. Select the type `channel existence`. +You can add the webhook in the Pusher Dashboard. +Select the type `channel existence`. diff --git a/docs/5/subscriptions/trigger-subscriptions.md b/docs/5/subscriptions/trigger-subscriptions.md index 8c283056b2..33307b4422 100644 --- a/docs/5/subscriptions/trigger-subscriptions.md +++ b/docs/5/subscriptions/trigger-subscriptions.md @@ -1,12 +1,10 @@ # Trigger Subscriptions -Now that clients can subscribe to a field, you will need to notify Lighthouse -when the underlying data has changed. +Now that clients can subscribe to a field, you will need to notify Lighthouse when the underlying data has changed. ## Broadcast Directive -The [@broadcast](../api-reference/directives.md#broadcast) -directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. +The [@broadcast](../api-reference/directives.md#broadcast) directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. ```graphql type Mutation { @@ -15,13 +13,11 @@ type Mutation { } ``` -You can reference the same subscription from multiple fields, or vice-versa -trigger multiple subscriptions from a single field. +You can reference the same subscription from multiple fields, or vice-versa trigger multiple subscriptions from a single field. ## Fire Subscriptions From Code -The `Subscription` class offers a utility method `broadcast` -that can be used to broadcast subscriptions from anywhere in your application. +The `Subscription` class offers a utility method `broadcast` that can be used to broadcast subscriptions from anywhere in your application. It accepts three parameters: @@ -29,8 +25,7 @@ It accepts three parameters: - `mixed $root` The result object you want to pass through - `bool $shouldQueue = null` Optional, overrides the default configuration `lighthouse.subscriptions.queue_broadcasts` -The following example shows how to trigger a subscription after an update -to the `Post` model. +The following example shows how to trigger a subscription after an update to the `Post` model. ```php $post->title = $newTitle; diff --git a/docs/5/testing/extensions.md b/docs/5/testing/extensions.md index b6cd17e23b..71fcc39847 100644 --- a/docs/5/testing/extensions.md +++ b/docs/5/testing/extensions.md @@ -1,12 +1,10 @@ # Testing Lighthouse extensions -When you extend Lighthouse with custom functionality, it is a great idea to test -your extensions in isolation from the rest of your application. +When you extend Lighthouse with custom functionality, it is a great idea to test your extensions in isolation from the rest of your application. ## Use a test schema -When you enhance functionality related to the schema definition, such as adding -a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. +When you enhance functionality related to the schema definition, such as adding a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. Add the `UsesTestSchema` trait to your base test class, call `setUpTestSchema()` and define your test schema: ```php @@ -40,8 +38,8 @@ class MyCustomDirectiveTest extends TestCase ## Mock resolvers -When testing custom functionality through a dummy schema, you still need to have -a way to resolve fields. Lighthouse provides a simple way to mock resolvers in a dummy schema. +When testing custom functionality through a dummy schema, you still need to have a way to resolve fields. +Lighthouse provides a simple way to mock resolvers in a dummy schema. Add the `MocksResolvers` trait to your test class: @@ -90,9 +88,9 @@ public function testReverseField(): void } ``` -Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert -that our resolver is called with certain values. Note that we are not passing an -explicit resolver function here. The default resolver will simply return `null`. +Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert that our resolver is called with certain values. +Note that we are not passing an explicit resolver function here. +The default resolver will simply return `null`. ```php public function testReverseInput(): void @@ -118,8 +116,7 @@ public function testReverseInput(): void } ``` -If you have to handle the incoming resolver arguments dynamically, you can also -pass a function that is called: +If you have to handle the incoming resolver arguments dynamically, you can also pass a function that is called: ```php public function testReverseInput(): void @@ -146,8 +143,8 @@ public function testReverseInput(): void } ``` -You might have a need to add multiple resolvers to a single schema. For that case, -specify a unique `key` for the mock resolver (it defaults to `default`): +You might have a need to add multiple resolvers to a single schema. +For that case, specify a unique `key` for the mock resolver (it defaults to `default`): ```php public function testMultipleResolvers(): void diff --git a/docs/5/testing/phpunit.md b/docs/5/testing/phpunit.md index 32112a2c63..2b75db5f1a 100644 --- a/docs/5/testing/phpunit.md +++ b/docs/5/testing/phpunit.md @@ -4,8 +4,8 @@ Lighthouse makes it easy to add automated tests through [PHPUnit](https://phpuni ## Setup -Lighthouse offers some useful test helpers that make it easy to call your API -from within a PHPUnit test. Just add the `MakesGraphQLRequests` trait to your test class. +Lighthouse offers some useful test helpers that make it easy to call your API from within a PHPUnit test. +Just add the `MakesGraphQLRequests` trait to your test class. ```diff +use Nuwave\Lighthouse\Testing\MakesGraphQLRequests; @@ -18,8 +18,8 @@ abstract class TestCase extends BaseTestCase } ``` -Enabling the schema cache speeds up your tests. To ensure the schema is fresh -before running tests, add the `RefreshesSchemaCache` trait to your test class and call it during set up. +Enabling the schema cache speeds up your tests. +To ensure the schema is fresh before running tests, add the `RefreshesSchemaCache` trait to your test class and call it during set up. ```diff +use Nuwave\Lighthouse\Testing\RefreshesSchemaCache; @@ -77,11 +77,9 @@ public function testCreatePost(): void ## Assertions -Now that we know how to query our server in tests, we need to make sure the -returned results match our expectations. +Now that we know how to query our server in tests, we need to make sure the returned results match our expectations. -The returned `TestResponse` conveniently offers assertions that work quite -well with the JSON data returned by GraphQL. +The returned `TestResponse` conveniently offers assertions that work quite well with the JSON data returned by GraphQL. The `assertJson` method asserts that the response is a superset of the given JSON. @@ -165,12 +163,9 @@ $this ## Testing Errors -Depending on your debug and error handling configuration, Lighthouse catches most if -not all errors produced within queries and includes them within the result. +Depending on your debug and error handling configuration, Lighthouse catches most if not all errors produced within queries and includes them within the result. -One way to test for errors is to examine the `TestResponse`, either by looking -at the JSON response manually or by using the provided [assertion mixins](#testresponse-assertion-mixins) -such as `assertGraphQLErrorMessage()`: +One way to test for errors is to examine the `TestResponse`, either by looking at the JSON response manually or by using the provided [assertion mixins](#testresponse-assertion-mixins) such as `assertGraphQLErrorMessage()`: ```php $this @@ -200,8 +195,7 @@ $this->graphQL(/** @lang GraphQL */ ' Lighthouse allows you to [upload files](../digging-deeper/file-uploads.md) through GraphQL. -Since multipart form requests are tricky to construct, you can just use the `multipartGraphQL` -helper method. +Since multipart form requests are tricky to construct, you can just use the `multipartGraphQL` helper method. ```php $operations = [ @@ -228,8 +222,8 @@ $this->multipartGraphQL($operations, $map, $file); ## Introspection -If you create or manipulate parts of your schema programmatically, you might -want to test that. You can use introspection to query your final schema in tests. +If you create or manipulate parts of your schema programmatically, you might want to test that. +You can use introspection to query your final schema in tests. Lighthouse uses the introspection query from [`\GraphQL\Type\Introspection::getIntrospectionQuery()`](https://github.com/webonyx/graphql-php/blob/master/src/Type/Introspection.php). @@ -295,8 +289,7 @@ $this->setUpDeferStream(); ## Lumen -Because the `TestResponse` class is not available in Lumen, you must use a different -test trait: +Because the `TestResponse` class is not available in Lumen, you must use a different test trait: ```diff ` -and including it in your schema. Lighthouse will look for Scalar types in a configurable -default namespace. +Define your own scalar types by running `php artisan lighthouse:scalar ` and including it in your schema. +Lighthouse will look for Scalar types in a configurable default namespace. ```graphql scalar ZipCode @@ -85,8 +83,8 @@ type Query { } ``` -In this example, the underlying values are actually integers. When the models are retrieved from -the database, the mapping is applied and the integers are converted to the defined string keys. +In this example, the underlying values are actually integers. +When the models are retrieved from the database, the mapping is applied and the integers are converted to the defined string keys. ```php return [ @@ -131,8 +129,7 @@ The PHP internal value of the field `ADMIN` will be `string('ADMIN')`. ### Native PHP definition -If you want to reuse enum definitions or constants from PHP, you can also -register a native PHP enum type [through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types). +If you want to reuse enum definitions or constants from PHP, you can also register a native PHP enum type [through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types). Just define an [EnumType](https://webonyx.github.io/graphql-php/type-definitions/enums) and register it: @@ -165,8 +162,7 @@ $typeRegistry = app(TypeRegistry::class); $typeRegistry->register($episodeEnum); ``` -If you are using [bensampo/laravel-enum](https://github.com/BenSampo/laravel-enum) -you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. +If you are using [bensampo/laravel-enum](https://github.com/BenSampo/laravel-enum) you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. ```php use BenSampo\Enum\Enum; @@ -261,8 +257,7 @@ enum Color { ## Input Input types can be used to describe complex objects for field arguments. -Beware that while they look similar to Object Types, they behave differently: -The fields of an Input Type are treated similar to arguments. +Beware that while they look similar to Object Types, they behave differently: The fields of an Input Type are treated similar to arguments. ```graphql input CreateUserInput { @@ -310,21 +305,19 @@ type User implements Named { } ``` -Interfaces need a way of determining which concrete Object Type is returned by a -particular query. Lighthouse provides a default type resolver that works by calling -`class_basename($value)` on the value returned by the resolver. +Interfaces need a way of determining which concrete Object Type is returned by a particular query. +Lighthouse provides a default type resolver that works by calling `class_basename($value)` on the value returned by the resolver. -You can also provide a custom type resolver. Run `php artisan lighthouse:interface ` to create -a custom interface class. It is automatically put in the default namespace where Lighthouse can discover it by itself. +You can also provide a custom type resolver. +Run `php artisan lighthouse:interface ` to create a custom interface class. +It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) ## Union A Union is an abstract type that simply enumerates other Object Types. -They are similar to interfaces in that they can return different types, but they can not -have fields defined. +They are similar to interfaces in that they can return different types, but they can not have fields defined. ```graphql union Person = User | Employee @@ -338,10 +331,8 @@ type Employee { } ``` -Just like Interfaces, you need a way to determine the concrete Object Type for a Union, -based on the resolved value. If the default type resolver does not work for you, define your -own using `php artisan lighthouse:union `. +Just like Interfaces, you need a way to determine the concrete Object Type for a Union, based on the resolved value. +If the default type resolver does not work for you, define your own using `php artisan lighthouse:union `. It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) diff --git a/docs/6/api-reference/commands.md b/docs/6/api-reference/commands.md index 165d3d9f08..fa06f98ca1 100644 --- a/docs/6/api-reference/commands.md +++ b/docs/6/api-reference/commands.md @@ -51,8 +51,7 @@ This will create the following files: - `programmatic-types.graphql`: Schema definitions for programmatically registered types, if you have any - `_lighthouse_ide_helper.php`: Class definitions for some magical PHP, such as the `TestResponse` mixin -A great way to keep up to date with your current version of Lighthouse -is to add this script to your `composer.json`: +A great way to keep up to date with your current version of Lighthouse is to add this script to your `composer.json`: ```json "scripts": { @@ -62,8 +61,7 @@ is to add this script to your `composer.json`: ], ``` -If the generated definitions conflict with those provided by your IDE, try `--omit-built-in` to avoid redefining -built-in directives such as `@deprecated`. +If the generated definitions conflict with those provided by your IDE, try `--omit-built-in` to avoid redefining built-in directives such as `@deprecated`. ## interface @@ -94,7 +92,8 @@ php artisan lighthouse:print-schema This can be quite useful, as the root `.graphql` files do not necessarily contain the whole schema. Schema imports, native PHP types and schema manipulation may influence the final schema. -Use the `-W` / `--write` option to output the schema to the default file storage (usually `storage/app`) as `lighthouse-schema.graphql`. +Use the `-W` / `--write` option to output the schema to default file storage (usually `storage/app`). +The output file is `lighthouse-schema.graphql`. You can output your schema in JSON format by using the `--json` flag. You can sort the final compiled schema by using the `--sort` flag. diff --git a/docs/6/api-reference/directives.md b/docs/6/api-reference/directives.md index e64493b483..bf38e891ae 100644 --- a/docs/6/api-reference/directives.md +++ b/docs/6/api-reference/directives.md @@ -131,8 +131,9 @@ directive @all( ) on FIELD_DEFINITION ``` -This assumes your model has the same name as the type you are returning and is defined -in the default model namespace `App`. [You can change this configuration](../getting-started/configuration.md). +This assumes your model has the same name as the returned type. +It also assumes the model is in the default namespace `App`. +[You can change this configuration](../getting-started/configuration.md). ```graphql type Query { @@ -194,8 +195,7 @@ type Query { } ``` -If you need to use a guard besides the default to resolve the authenticated user, -you can pass the guard name as the `guards` argument. +If you need to use a guard besides the default to resolve the authenticated user, you can pass the guard name as the `guards` argument. ```graphql type Query { @@ -256,8 +256,8 @@ final class Post extends Model } ``` -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument. +Use it when your relationship method name differs from the field name. ```graphql type Post { @@ -320,7 +320,8 @@ enum BelongsToManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -356,8 +357,8 @@ final class User extends Model ### Rename Relation -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument. +Use it when your relationship method name differs from the field name. ```graphql type User { @@ -371,12 +372,10 @@ You may want to allow accessing data that describes the relation between the mod See [retrieving intermediate table columns in Laravel](https://laravel.com/docs/eloquent-relationships#retrieving-intermediate-table-columns). Just like in Laravel, you can access the `pivot` attribute on the models (or its alias). -Even though this attribute is always present when querying the model through the relation, -it may not be present when reaching the node through another path in the schema, so it is -recommended to define the field as nullable (no `!`). +Even though this attribute is always present when querying the model through the relation, it may not be present when reaching the node through another path in the schema. +It is recommended to define the field as nullable (no `!`). -The following example assumes the intermediate table between `User` and `Role` defines -a column `meta`. +The following example assumes the intermediate table between `User` and `Role` defines a column `meta`. ```php use Illuminate\Database\Eloquent\Model; @@ -419,8 +418,7 @@ type RoleUserPivot { } ``` -When using the `type` argument with pagination style `CONNECTION`, you may create your own [edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) -that either contains the attributes of the intermediate table or contains a `pivot` field with the corresponding type. +When using the `type` argument with pagination style `CONNECTION`, you may create your own [edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) that either contains the attributes of the intermediate table or contains a `pivot` field with the corresponding type. The custom edge type must contain at least the following two fields: @@ -569,8 +567,7 @@ final class CompanyBinding ### Binding a collection of instances -When the `@bind` directive is defined on an argument or input field with an array value, -it can be used to resolve a collection of instances. +When the `@bind` directive is defined on an argument or input field with an array value, it can be used to resolve a collection of instances. ```graphql type Mutation { @@ -642,8 +639,7 @@ type Mutation { } ``` -You may override the default queueing behavior from the configuration by -passing the `shouldQueue` argument. +You may override the default queueing behavior from the configuration by passing the `shouldQueue` argument. ```graphql type Mutation { @@ -679,16 +675,17 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar BuilderValue ``` -You must point to a `method` which will receive the builder instance -and can apply additional constraints to the query. +You must point to a `method` that receives the builder instance. +That method can apply additional constraints to the query. -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). -When used on an argument, the method is only called when the argument is specified (may be `null`), -and its value is passed as the second parameter. -When used on a field, the method is always called, and if the `value` argument is defined, -it is passed as the second parameter. +When used on an argument, the method is only called when the argument is specified (may be `null`). +And its value is passed as the second parameter. +When used on a field, the method is always called. +And if the `value` argument is defined, it is passed as the second parameter. ```graphql type Query { @@ -798,11 +795,13 @@ You can find usage examples of this directive in [the caching docs](../performan ## @can -Deprecated. Use the [@can\* family of directives](#can-family-of-directives) instead. +Deprecated. +Use the [@can\* family of directives](#can-family-of-directives) instead. ## @can\* family of directives -All `@can*` directives have common arguments. These arguments specify how gates are checked and what to do if the user is not authorized. +All `@can*` directives have common arguments. +These arguments specify how gates are checked and what to do if the user is not authorized. Each directive has its own set of arguments that specify what to check against. ```graphql @@ -1025,8 +1024,7 @@ type Query { } ``` -A custom complexity function may look like the following, -refer to the [complexity function signature](resolvers.md#complexity-function-signature). +A custom complexity function may look like the following, refer to the [complexity function signature](resolvers.md#complexity-function-signature). ```php namespace App\GraphQL\Security; @@ -1071,8 +1069,8 @@ type Mutation { } ``` -Non-nullable arguments will _not_ be converted when this directive is used on a field, -but will be converted when it is used directly on the argument. +Non-nullable arguments will _not_ be converted when this directive is used on a field. +But will be converted when it is used directly on the argument. ```graphql type Mutation { @@ -1083,8 +1081,7 @@ type Mutation { } ``` -If you want this for all your fields, consider adding this directive to your -global field middleware in `lighthouse.php`: +If you want this for all your fields, add this directive to your global field middleware in `lighthouse.php`: ```php 'field_middleware' => [ @@ -1177,8 +1174,7 @@ type Mutation { } ``` -If you are using a single input object as an argument, you must tell Lighthouse -to spread out the nested values before applying it to the resolver. +If you are using a single input object as an argument, you must tell Lighthouse to spread out the nested values before applying it to the resolver. ```graphql type Mutation { @@ -1190,8 +1186,8 @@ input CreatePostInput { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, set it with the `model` argument. +If the model is in a non-default namespace, also set it with the `model` argument. ```graphql type Mutation { @@ -1282,8 +1278,8 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, set it with the `model` argument. +If the model is in a non-default namespace, also set it with the `model` argument. ```graphql type Mutation { @@ -1300,9 +1296,7 @@ type Mutation { } ``` -If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or -`MorphTo` relationship, you can pass a Boolean instead of an ID, as there is only one -possible model that can be deleted. +If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or `MorphTo` relationship, you can pass a Boolean instead of an ID, as there is only one possible model that can be deleted. ```graphql type Mutation { @@ -1337,8 +1331,8 @@ type Query { } ``` -Deprecated elements are not included in introspection queries by default, -but they can still be queried by clients. +Deprecated elements are not included in introspection queries by default. +But they can still be queried by clients. ## @drop @@ -1349,8 +1343,8 @@ Ignore the user given value, don't pass it to the resolver. directive @drop on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -This is useful when you want to deprecate a field, but avoid breaking changes -for clients that still pass the value. +This is useful when you want to deprecate a field. +But avoid breaking changes for clients that still pass the value. ```graphql type User { @@ -1397,9 +1391,7 @@ enum FeatureState { } ``` -Requires the installation of [Laravel Pennant](https://laravel.com/docs/pennant) -and manual registration of the service provider `Nuwave\Lighthouse\Pennant\PennantServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Requires the installation of [Laravel Pennant](https://laravel.com/docs/pennant) and manual registration of the service provider `Nuwave\Lighthouse\Pennant\PennantServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## @field @@ -1429,8 +1421,7 @@ type Mutation { } ``` -You can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md), -The following will look for a class in `App\GraphQL\Queries` by default. +You can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md), The following will look for a class in `App\GraphQL\Queries` by default. ```graphql type Query { @@ -1438,8 +1429,8 @@ type Query { } ``` -Be aware that resolvers are not limited to root fields. A resolver can be used for basic tasks -such as transforming the value of scalar fields, e.g. reformat a date. +Be aware that resolvers are not limited to root fields. +A resolver can be used for basic tasks such as transforming the value of scalar fields, e.g. reformat a date. ```graphql type User { @@ -1580,8 +1571,8 @@ enum Role { } ``` -You do not need this directive if the internal value of each enum key -is an identical string. [Read more about enum types](../the-basics/types.md#enum) +You do not need this directive if the internal value of each enum key is an identical string. +[Read more about enum types](../the-basics/types.md#enum) ## @eq @@ -1611,7 +1602,8 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar EqValue ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -1620,8 +1612,7 @@ type User { } ``` -If the name of the argument does not match the database column, -pass the actual column name as the `key`. +If the name of the argument does not match the database column, pass the actual column name as the `key`. ```graphql type User { @@ -1710,8 +1701,7 @@ enum GlobalIdDecode { } ``` -Instead of the original ID, the `id` field will now return a base64-encoded String -that globally identifies the User and can be used for querying the `node` endpoint. +Instead of the original ID, the `id` field will now return a base64-encoded String that globally identifies the User and can be used for querying the `node` endpoint. ```graphql type User { @@ -1720,8 +1710,7 @@ type User { } ``` -The field resolver will receive the decoded version of the passed `id`, -split into type and ID. +The field resolver will receive the decoded version of the passed `id`, split into type and ID. ```graphql type Mutation { @@ -1729,8 +1718,7 @@ type Mutation { } ``` -You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global IDs. +You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global IDs. ## @guard @@ -1765,15 +1753,13 @@ To ensure the user is logged in, add the `AttemptAuthenticate` middleware to you ], ``` -A useful pattern is to group fields in an `extend type` to apply [@guard](#guard) -on all of them at once. +A useful pattern is to group fields in an `extend type` to apply [@guard](#guard) on all of them at once. ```graphql extend type Query @guard { ... } ``` -The [@guard](#guard) directive will be prepended to other directives defined on the fields -and thus executes before them. +The [@guard](#guard) directive will be prepended to other directives defined on the fields and thus executes before them. ```graphql extend type Query { @@ -1859,7 +1845,8 @@ enum HasManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -1886,8 +1873,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model differs from the field name, -you can override it by setting `relation`. +If the relationship name on the Eloquent model differs from the field name, set `relation` to override it. ```graphql type User { @@ -1950,7 +1936,8 @@ enum HasManyThroughType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -1989,8 +1976,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model differs from the field name, -you can override it by setting `relation`. +If the relationship name on the Eloquent model differs from the field name, set `relation` to override it. ```graphql type User { @@ -2024,8 +2010,7 @@ type Mechanic { } ``` -If the name of the relationship on the Eloquent model differs from the field name, -you can override it by setting `relation`. +If the relationship name on the Eloquent model differs from the field name, set `relation` to override it. ```graphql type Mechanic { @@ -2048,7 +2033,8 @@ directive @in( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -2080,8 +2066,8 @@ directive @inject( ) repeatable on FIELD_DEFINITION ``` -This is useful to ensure that the authenticated user's `id` is -automatically used for creating new models and cannot be manipulated. +This ensures the authenticated user `id` is used automatically when creating new models. +It cannot be manipulated by clients. ```graphql type Mutation { @@ -2091,8 +2077,7 @@ type Mutation { } ``` -If you are using an Input Object as an argument, you can use dot notation to -set a nested argument. +If you are using an Input Object as an argument, you can use dot notation to set a nested argument. ```graphql type Mutation { @@ -2118,8 +2103,8 @@ directive @interface( ) on INTERFACE ``` -Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding -to use this directive, you probably don't need it. +Read the [basics about Interfaces](../the-basics/types.md#interface) before deciding to use this directive. +You probably do not need it. Set the `resolveType` argument to a function that returns the implementing Object Type. @@ -2130,8 +2115,8 @@ interface Commentable } ``` -The function receives the value of the parent field as its single argument and must -return an Object Type. You can get the appropriate Object Type from Lighthouse's type registry. +The function receives the value of the parent field as its single argument and must return an Object Type. +You can get the appropriate Object Type from Lighthouse's type registry. ```php namespace App\GraphQL\Interfaces; @@ -2230,7 +2215,8 @@ directive @like( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ## @limit @@ -2285,8 +2271,7 @@ Lighthouse will return at most the number of results that the client requested. } ``` -If your field is resolved through a database query, you may add the `builder` argument to apply -an actual `LIMIT` clause to your SQL: +If your field is resolved through a database query, you may add the `builder` argument to apply an actual `LIMIT` clause to your SQL: ```graphql type Query { @@ -2334,8 +2319,8 @@ Ensure the order of the argument definition matches the parameters of your metho public function purchasedItemsCount(int $year, ?bool $includeReturns) ``` -Lighthouse will always pass down the same number of arguments and default to `null` -if the client passes nothing. +Lighthouse always passes down the same number of arguments. +It defaults to `null` if the client passes nothing. ```graphql { @@ -2430,7 +2415,8 @@ enum MorphManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -2568,7 +2554,8 @@ enum MorphToManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -2589,8 +2576,7 @@ The arguments are a map from directive names to namespaces. directive @namespace repeatable on FIELD_DEFINITION | OBJECT ``` -The following example applies the namespace `App\Blog` -to the [@field](#field) directive used on the `posts` field. +The following example applies the namespace `App\Blog` to the [@field](#field) directive used on the `posts` field. ```graphql type Query { @@ -2600,9 +2586,8 @@ type Query { } ``` -When used upon an object type or an object type extension, the namespace -applies to fields of the type as well. This allows you to specify -a common namespace for a group of fields. +When used upon an object type or an object type extension, the namespace applies to fields of the type as well. +This allows you to specify a common namespace for a group of fields. ```graphql extend type Query @namespace(field: "App\\Blog") { @@ -2660,7 +2645,8 @@ directive @neq( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -2746,8 +2732,7 @@ type Query { } ``` -Lighthouse defaults to resolving types through the underlying model, -for example by calling `User::find($id)`. +Lighthouse defaults to resolving types through the underlying model, for example by calling `User::find($id)`. ```graphql type User @node { @@ -2763,8 +2748,8 @@ type Country @node(resolver: "App\\Countries@byId") { } ``` -The `resolver` argument has to specify a function which will be passed the -decoded `id` and resolves to a result. +The `resolver` argument must specify a function. +It receives the decoded `id` and resolves to a result. ```php public function byId($id): array @@ -2778,8 +2763,8 @@ public function byId($id): array [Read more](../digging-deeper/relay.md#global-object-identification). -Behind the scenes, Lighthouse will decode the global ID sent from the client -to find the model by its primary key in the database. +Behind the scenes, Lighthouse decodes the global ID sent by the client. +It then finds the model by its primary key in the database. ## @notIn @@ -2796,7 +2781,8 @@ directive @notIn( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -2887,7 +2873,8 @@ input OrderByRelation { } ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). See [ordering](../digging-deeper/ordering.md). @@ -2965,7 +2952,8 @@ enum PaginateType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -3058,9 +3046,8 @@ It can be queried like this: ### Pagination type -The `type` of pagination defaults to `PAGINATOR`, -but may also be set to `SIMPLE` (see [Simple Pagination](#simple-pagination)) -or a Relay compliant `CONNECTION`. +The `type` of pagination defaults to `PAGINATOR`. +May also be set to `SIMPLE` (see [Simple Pagination](#simple-pagination)) or a Relay compliant `CONNECTION`. > Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -3105,9 +3092,9 @@ type PostEdge { ### Simple Pagination -In contrast to other pagination types, `SIMPLE` pagination only fires a single database -query on every request. This improves performance, but means that the response does not -hold information about the total number of items. +In contrast to other pagination types, `SIMPLE` pagination fires only one database query per request. +This improves performance. +But means that the response does not hold information about the total number of items. If you wish to use the `simplePaginate` method, set the `type` to `SIMPLE`. @@ -3205,9 +3192,9 @@ query { ### Limit maximum count -Lighthouse allows you to specify a global maximum for the number of items a user -can request through pagination through the config. You may also overwrite this -per field with the `maxCount` argument: +Lighthouse allows you to specify a global maximum for items requested through pagination. +Configure this through the config. +You may also overwrite this per field with the `maxCount` argument: ```graphql type Query { @@ -3217,8 +3204,9 @@ type Query { ### Overwrite model -By default, Lighthouse looks for an Eloquent model in the configured default namespace, with the same -name as the returned type. You can overwrite this by setting the `model` argument. +By default, Lighthouse looks for an Eloquent model in the configured default namespace. +It expects the same name as the returned type. +You can overwrite this by setting the `model` argument. ```graphql type Query { @@ -3236,7 +3224,8 @@ type Query { } ``` -Your method receives the typical resolver arguments and has to return an instance of `Illuminate\Database\Query\Builder`. +Your method receives the typical resolver arguments. +It must return an instance of `Illuminate\Database\Query\Builder`. > If you actually want to query a model and possibly its relations through nested fields, > make sure to return an Eloquent builder, e.g. `Post::query()`. @@ -3264,7 +3253,8 @@ final class Blog You can provide your own function that resolves the field by directly returning data in a `Illuminate\Contracts\Pagination\Paginator` instance. -This is mutually exclusive with `builder` and `model`. Not compatible with `scopes` and builder arguments such as [@eq](#eq). +This is mutually exclusive with `builder` and `model`. +Not compatible with `scopes` and builder arguments such as [@eq](#eq). ```graphql type Query { @@ -3320,8 +3310,7 @@ directive @rename( ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -This can often be useful to ensure consistent naming of your schema -without having to change the underlying models. +This can often be useful to ensure consistent naming of your schema without having to change the underlying models. ```graphql type User { @@ -3525,7 +3514,8 @@ directive @scope( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -3568,12 +3558,10 @@ directive @search( ) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -Requires the installation of [Laravel Scout](https://laravel.com/docs/scout) -and manual registration of the service provider `Nuwave\Lighthouse\Scout\ScoutServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Requires the installation of [Laravel Scout](https://laravel.com/docs/scout) and manual registration of the service provider `Nuwave\Lighthouse\Scout\ScoutServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). -The `search()` method of the model is called with the value of the argument, -using the driver you configured for Scout. +The model `search()` method is called with the argument value. +It uses the Scout driver you configured. ```graphql type Query { @@ -3581,8 +3569,7 @@ type Query { } ``` -The [@search](#search) directive only works in combination with filter directives that -implement the interface `Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: +The [@search](#search) directive only works in combination with filter directives that implement the interface `Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: - [@eq](#eq) - [@softDeletes](#softdeletes) @@ -3590,10 +3577,8 @@ implement the interface `Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: Scout is only activated if an argument annotated with [@search](#search) is present with a string value. Passing `null` behaves the same as leaving the argument out and falls back to a database query. -When using [@convertEmptyStringsToNull](#convertemptystringstonull), nullable `String` arguments with an empty -string value may be converted to `null` and therefore not activate Scout. -If you need empty-string search behavior, prefer an explicit schema contract such as a dedicated search field -or a non-null search argument. +When using [@convertEmptyStringsToNull](#convertemptystringstonull), nullable `String` arguments with an empty string value may be converted to `null` and therefore not activate Scout. +If you need empty-string search behavior, prefer an explicit schema contract such as a dedicated search field or a non-null search argument. Normally the search will be performed using the index specified by the model's `searchableAs` method. However, in some situation a custom index might be needed, this can be achieved by using the argument `within`. @@ -3693,8 +3678,7 @@ mutation { } ``` -Internally, the arguments will be transformed into a flat structure before -they are passed along to the resolver: +Internally, the arguments are transformed into a flat structure before they are passed to the resolver: ```php [ @@ -3704,8 +3688,7 @@ they are passed along to the resolver: ] ``` -Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/field-argument-directives) -have been applied, e.g. validation, transformation. +Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/field-argument-directives) have been applied, e.g. validation, transformation. ## @subscription @@ -3722,8 +3705,8 @@ directive @subscription( ) on FIELD_DEFINITION ``` -If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md) -you do not need this directive. It is only useful if you need to override the default namespace. +If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md), you do not need this directive. +It is only useful if you need to override the default namespace. ```graphql type Subscription { @@ -3761,11 +3744,12 @@ directive @throttle( ) on FIELD_DEFINITION ``` -Allows use Laravel throttling on a per-field basis. See [Laravel doc](https://laravel.com/docs/routing#rate-limiting) -on how to configure named limiters. +Allows use Laravel throttling on a per-field basis. +See [Laravel doc](https://laravel.com/docs/routing#rate-limiting) on how to configure named limiters. -Limiters that return `response` are not supported. Hashes are different from the ones of Laravel, so one can't use -one named limiter to limit both Laravel route and GraphQL field. +Limiters that return `response` are not supported. +Hashes are different from the ones of Laravel. +So one can't use one named limiter to limit both Laravel route and GraphQL field. ## @trashed @@ -3776,13 +3760,13 @@ Allows to filter if trashed elements should be fetched. directive @trashed on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). The most convenient way to use this directive is through [@softDeletes](#softdeletes). -If you want to add it manually, make sure the argument is of the -enum type `Trashed`: +If you want to add it manually, make sure the argument is of the enum type `Trashed`: ```graphql type Query { @@ -3819,8 +3803,7 @@ type Mutation { } ``` -If you want this for all your fields, consider adding this directive to your -global field middleware in `lighthouse.php`: +If you want this for all your fields, add this directive to your global field middleware in `lighthouse.php`: ```php 'field_middleware' => [ @@ -3845,8 +3828,8 @@ directive @union( ) on UNION ``` -Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding -to use this directive, you probably don't need it. +Read the [basics about Unions](../the-basics/types.md#union) before deciding to use this directive. +You probably do not need it. ```graphql type User { @@ -3862,8 +3845,8 @@ union Person @union(resolveType: "App\\GraphQL\\Unions\\Person@resolveType") = | Employee ``` -The function receives the value of the parent field as its single argument and must -resolve an Object Type from Lighthouse's `TypeRegistry`. +The function receives the value of the parent field as its single argument. +It must resolve an Object Type from Lighthouse `TypeRegistry`. ```php namespace App\GraphQL\Unions; @@ -3931,8 +3914,8 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, set it with the `model` argument. +If the model is in a non-default namespace, also set it with the `model` argument. ```graphql type Mutation { @@ -4150,7 +4133,8 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar WhereValue ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). You can specify simple operators: @@ -4221,10 +4205,11 @@ directive @whereAuth( ) on FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). -The following query returns all posts that belong to the currently authenticated user. +The following query returns all posts that belong to the currently authenticated user. Behind the scenes it is using a `whereHas` query. ```graphql @@ -4251,7 +4236,8 @@ directive @whereBetween( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). This example defines an `input` to filter that a value is between two dates. @@ -4267,8 +4253,8 @@ input DateRange { } ``` -You may use any custom `input` type for the argument. Make sure it has -exactly two required fields to ensure the query is valid. +You may use any custom `input` type for the argument. +Make sure it has exactly two required fields to ensure the query is valid. ## @whereConditions @@ -4293,7 +4279,8 @@ directive @whereJsonContains( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4361,7 +4348,8 @@ directive @whereNotBetween( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4398,7 +4386,8 @@ directive @whereNotNull( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4428,7 +4417,8 @@ directive @whereNull( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4457,8 +4447,8 @@ directive @with( ) repeatable on FIELD_DEFINITION ``` -This can be a useful optimization for fields that are not returned directly -but rather used for resolving other fields. +This can be a useful optimization for fields that are not returned directly. +It is useful when fields are only used to resolve other fields. ```graphql type User { @@ -4466,7 +4456,7 @@ type User { } ``` -If you just want to return the relation itself as-is, look into [handling Eloquent relationships](../eloquent/relationships.md). +If you just want to return the relation as-is, see [handling Eloquent relationships](../eloquent/relationships.md). ## @withCount @@ -4518,7 +4508,8 @@ directive @withoutGlobalScopes( ) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```php diff --git a/docs/6/api-reference/scalars.md b/docs/6/api-reference/scalars.md index a3016499b5..a06ffb6273 100644 --- a/docs/6/api-reference/scalars.md +++ b/docs/6/api-reference/scalars.md @@ -1,7 +1,6 @@ # Scalars -You can use Lighthouse's built-in scalars by defining them in your schema, -using [@scalar](directives.md#scalar) to point them to a FQCN. +You can use Lighthouse's built-in scalars by defining them in your schema, using [@scalar](directives.md#scalar) to point them to a FQCN. ```graphql "A datetime string with format `Y-m-d H:i:s`, e.g. `2018-05-23 13:43:32`." @@ -66,6 +65,4 @@ scalar Upload This Scalar can only be used as an argument, not as a return type. For more information, please refer to the [file uploads guide](../digging-deeper/file-uploads.md). -The multipart form request is handled by Lighthouse, the resolver gets passed -an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) -in the argument `array $variables`. +The multipart form request is handled by Lighthouse, the resolver gets passed an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) in the argument `array $variables`. diff --git a/docs/6/concepts/arg-resolvers.md b/docs/6/concepts/arg-resolvers.md index a3ce0d91b9..55c88bb130 100644 --- a/docs/6/concepts/arg-resolvers.md +++ b/docs/6/concepts/arg-resolvers.md @@ -1,26 +1,20 @@ # Arg Resolvers -To understand the concept behind arg resolvers, you should familiarize yourself with -[how field resolvers are composed](https://graphql.org/learn/execution). +To understand the concept behind arg resolvers, you should familiarize yourself with [how field resolvers are composed](https://graphql.org/learn/execution). ## Motivation -Arg resolvers are an extension of the ideas behind GraphQL field execution, -applied to input arguments. Since GraphQL queries can be used to fetch complex -and deeply nested data from the client, it is natural to assume that such complex -data can also be passed as the input arguments to a query. +Arg resolvers are an extension of the ideas behind GraphQL field execution, applied to input arguments. +Since GraphQL queries can be used to fetch complex and deeply nested data from the client, it is natural to assume that such complex data can also be passed as the input arguments to a query. -GraphQL's execution engine allows you to write small and focused field resolver functions -that only care about returning the data that it is immediately responsible for. +GraphQL's execution engine allows you to write small and focused field resolver functions that only care about returning the data that it is immediately responsible for. That makes the code much simpler and avoids duplication. -However, a single field resolver still has to take care of all the input arguments that -are passed to it. Handling complex input data in a single function is hard because of their -dynamic nature. The input given by a client might be nested arbitrarily deep -and come in many different variations. +However, a single field resolver still has to take care of all the input arguments that are passed to it. +Handling complex input data in a single function is hard because of their dynamic nature. +The input given by a client might be nested arbitrarily deep and come in many different variations. -The following example shows an example mutation that is actually composed out of multiple -distinct operations. +The following example shows an example mutation that is actually composed out of multiple distinct operations. ```graphql type Mutation { @@ -38,8 +32,7 @@ input CreateNoteInput { } ``` -In a single request, we can pass all data relating to a task, -including related entities such as notes. +In a single request, we can pass all data relating to a task, including related entities such as notes. ```graphql mutation CreateTaskWithNotes { @@ -80,15 +73,13 @@ function createTaskWithNotes(mixed $root, array $args): \App\Models\Task { In this contrived example, the function is still quite small. However, separation of concerns is already violated: A single function is responsible for creating both tasks and notes. -We might want to extend our schema to support more operations in the future, such as updating -a task and creating, updating or deleting notes or other, more deeply nested relations. +We might want to extend our schema to support more operations in the future, such as updating a task and creating, updating or deleting notes or other, more deeply nested relations. Such changes would force us to duplicate code and increase the complexity of our single function. ## Solution -Ideally, we would want to write small and focused functions that deal with just -a part of the given input arguments. The execution engine should traverse the given -input and take care of calling the appropriate functions with their respective arguments. +Ideally, we would want to write small and focused functions that deal with just a part of the given input arguments. +The execution engine should traverse the given input and take care of calling the appropriate functions with their respective arguments. ```php function createTask(mixed $root, array $args): \App\Models\Task { @@ -128,8 +119,7 @@ input CreateNoteInput { The [@create](../api-reference/directives.md#create) directive will behave differently, based on the context where it is used. -On the `createTask` field, it will create a `Task` model with the given `name`, save it -to the database and return that instance to Lighthouse. +On the `createTask` field, it will create a `Task` model with the given `name`, save it to the database and return that instance to Lighthouse. A simplified, generic implementation of an appropriate field resolver would look something like this: @@ -164,8 +154,7 @@ final class CreateDirective extends BaseDirective implements FieldResolver ``` The arguments that are nested within `notes` will be handled as a nested argument resolver. -For each `CreateNoteInput`, the resolver will be called with the previously created `Task` -and create and attach a related `Note` model. +For each `CreateNoteInput`, the resolver will be called with the previously created `Task` and create and attach a related `Note` model. We can extend our previous implementation of [@create](../api-reference/directives.md#create) by allowing it to be used as an `ArgResolver`: diff --git a/docs/6/concepts/request-lifecycle.md b/docs/6/concepts/request-lifecycle.md index 0f02427f5a..e4f9716ea5 100644 --- a/docs/6/concepts/request-lifecycle.md +++ b/docs/6/concepts/request-lifecycle.md @@ -5,8 +5,7 @@ This section should provide an understanding of the involved steps, their order ## Routing -All requests to the configured GraphQL endpoint - usually `/graphql` - are routed -to the single `GraphQLController`. +All requests to the configured GraphQL endpoint - usually `/graphql` - are routed to the single `GraphQLController`. ## HTTP Middleware @@ -27,18 +26,17 @@ This step is typically cached for larger schemas, to enhance performance. ## Query Validation -The GraphQL query is validated to ensure it matches the schema. Lighthouse makes sure the requested -fields are available in the schema, and the correct variables are passed. +The GraphQL query is validated to ensure it matches the schema. +Lighthouse makes sure the requested fields are available in the schema, and the correct variables are passed. ## Field Execution Starting from the root level, the fields within the query are executed. -Each field may be wrapped with field middleware, which can add authentication, authorization, -fine-grained validation, and more. Finally, the field resolver is called to produce a value for the field. +Each field may be wrapped with field middleware, which can add authentication, authorization, fine-grained validation, and more. +Finally, the field resolver is called to produce a value for the field. -If the field contains a subselection, the same process happens for the nested fields, until -we either abort with an error or traversed the entire query tree. +If the field contains a subselection, the same process happens for the nested fields, until we either abort with an error or traversed the entire query tree. [Learn more about GraphQL execution](https://graphql.org/learn/execution). @@ -50,4 +48,5 @@ Lighthouse collects the errors to allow the rest of the query to execute. ## Result Assembly The execution results are assembled into a structure that resembles the query of the client. -Errors are properly formatted and included in the response. The response is sent to the client. +Errors are properly formatted and included in the response. +The response is sent to the client. diff --git a/docs/6/custom-directives/field-argument-directives.md b/docs/6/custom-directives/field-argument-directives.md index 97b7c0e345..d0407f8f88 100644 --- a/docs/6/custom-directives/field-argument-directives.md +++ b/docs/6/custom-directives/field-argument-directives.md @@ -4,11 +4,10 @@ Field argument directives can be applied to field arguments (see [Field Argument ## ArgManipulator -An [`Nuwave\Lighthouse\Support\Contracts\ArgManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgManipulator.php) -directive can be used to manipulate the schema AST of a field argument or its parents. +An [`Nuwave\Lighthouse\Support\Contracts\ArgManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgManipulator.php) directive can be used to manipulate the schema AST of a field argument or its parents. -For example, you might want to add a directive that automagically derives the arguments -for a field based on an object type. A skeleton for this directive might look something like this: +For example, you might want to add a directive that automagically derives the arguments for a field based on an object type. +A skeleton for this directive might look something like this: ```php namespace App\GraphQL\Directives; diff --git a/docs/6/custom-directives/field-directives.md b/docs/6/custom-directives/field-directives.md index 91da872947..fefe8bf3d4 100644 --- a/docs/6/custom-directives/field-directives.md +++ b/docs/6/custom-directives/field-directives.md @@ -4,18 +4,15 @@ Field directives can be applied to any [FieldDefinition](https://graphql.github. ## FieldResolver -Perhaps the most important directive interface, a [`Nuwave\Lighthouse\Support\Contracts\FieldResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldResolver.php) -lets you add a resolver for a field through a directive. +Perhaps the most important directive interface, a [`Nuwave\Lighthouse\Support\Contracts\FieldResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldResolver.php) lets you add a resolver for a field through a directive. It can be a great way to reuse resolver logic within a schema. ## FieldMiddleware -A [`Nuwave\Lighthouse\Support\Contracts\FieldMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldMiddleware.php) directive allows you -to wrap around the field resolver, just like [Laravel Middleware](https://laravel.com/docs/middleware). +A [`Nuwave\Lighthouse\Support\Contracts\FieldMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldMiddleware.php) directive allows you to wrap around the field resolver, just like [Laravel Middleware](https://laravel.com/docs/middleware). -You may use it to handle incoming values before reaching the final resolver -as well as the outgoing result of resolving the field. +You may use it to handle incoming values before reaching the final resolver as well as the outgoing result of resolving the field. ```php namespace App\GraphQL\Directives; @@ -64,8 +61,7 @@ type Query { ## FieldBuilderDirective -A [`Nuwave\Lighthouse\Support\Contracts\FieldBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/FieldBuilderDirective.php) -directive allows modifying the database query that Lighthouse creates for a field. +A [`Nuwave\Lighthouse\Support\Contracts\FieldBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/FieldBuilderDirective.php) directive allows modifying the database query that Lighthouse creates for a field. > This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](../api-reference/directives.md#all) or [@hasMany](../api-reference/directives.md#hasmany). @@ -76,17 +72,14 @@ The following directives use the defined filter for resolving the query: ## FieldManipulator -A [`Nuwave\Lighthouse\Support\Contracts\FieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldManipulator.php) -directive can be used to manipulate the schema AST. +A [`Nuwave\Lighthouse\Support\Contracts\FieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldManipulator.php) directive can be used to manipulate the schema AST. ## ValidationDirective -This directive type is implemented as an abstract class rather than a pure interface and allows -you to define complex validation rules for a field with ease. +This directive type is implemented as an abstract class rather than a pure interface and allows you to define complex validation rules for a field with ease. [Read more about it in the Validation section](../security/validation.md#validator-for-fields). ## ComplexityResolverDirective -A [`Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ComplexityResolverDirective.php) -directive allows you to overwrite the default query complexity calculation. +A [`Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ComplexityResolverDirective.php) directive allows you to overwrite the default query complexity calculation. diff --git a/docs/6/custom-directives/getting-started.md b/docs/6/custom-directives/getting-started.md index cef16eab8a..42959b95c0 100644 --- a/docs/6/custom-directives/getting-started.md +++ b/docs/6/custom-directives/getting-started.md @@ -20,8 +20,7 @@ Use the artisan generator command to create it: php artisan lighthouse:directive --argument upperCase ``` -That will create a class called `UpperCaseDirective` that extends the -abstract class `Nuwave\Lighthouse\Schema\Directives\BaseDirective`. +That will create a class called `UpperCaseDirective` that extends the abstract class `Nuwave\Lighthouse\Schema\Directives\BaseDirective`. ```php use Nuwave\Lighthouse\Schema\Directives\BaseDirective; @@ -95,13 +94,12 @@ It is advised to look at the Lighthouse source code to find directives that impl Now that we defined and implemented the directive, how can Lighthouse find it? -When Lighthouse encounters a directive within the schema, it starts looking for a matching class -in the following order: +When Lighthouse encounters a directive within the schema, it starts looking for a matching class in the following order: 1. User-defined namespaces as configured in `config/lighthouse.php`, defaults to `App\GraphQL\Directives` 1. The [RegisterDirectiveNamespaces](../api-reference/events.md#registerdirectivenamespaces) event is dispatched to gather namespaces defined by plugins, extensions or other listeners 1. Lighthouse's built-in directive namespace -This means that our directive is already registered, just by matter of defining it in the default namespace, -and will take precedence over potential other directives with the same name. +This means that our directive is already registered, just by matter of defining it in the default namespace. +Will take precedence over potential other directives with the same name. diff --git a/docs/6/custom-directives/input-field-directives.md b/docs/6/custom-directives/input-field-directives.md index 2a0ff6f98c..8e7b6b5553 100644 --- a/docs/6/custom-directives/input-field-directives.md +++ b/docs/6/custom-directives/input-field-directives.md @@ -4,8 +4,7 @@ Input field directives can be applied to input fields (see [InputFieldsDefinitio ## InputFieldManipulator -An [`Nuwave\Lighthouse\Support\Contracts\InputFieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/InputFieldManipulator.php) -directive can be used to manipulate the schema AST of an input field or its parent. +An [`Nuwave\Lighthouse\Support\Contracts\InputFieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/InputFieldManipulator.php) directive can be used to manipulate the schema AST of an input field or its parent. For example, the following directive automatically adds translations for the input field description. diff --git a/docs/6/custom-directives/input-value-directives.md b/docs/6/custom-directives/input-value-directives.md index e1668b7c18..0fb891b5e6 100644 --- a/docs/6/custom-directives/input-value-directives.md +++ b/docs/6/custom-directives/input-value-directives.md @@ -2,8 +2,7 @@ Some directives can be applied to field arguments or input fields (any [InputValueDefinition](https://graphql.github.io/graphql-spec/June2018/#InputValueDefinition)). -As arguments may be contained within a list in the schema definition, you must specify -what your directive should apply to in addition to its function. +As arguments may be contained within a list in the schema definition, you must specify what your directive should apply to in addition to its function. - If it applies to the individual items within the list, implement the [`Nuwave\Lighthouse\Support\Contracts\ArgDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgDirective.php) interface. @@ -14,8 +13,7 @@ You must implement exactly one of those two interfaces in order for an argument ## Evaluation Order -The application of directives that implement the `ArgDirective` interface is -split into three distinct phases: +The application of directives that implement the `ArgDirective` interface is split into three distinct phases: - Sanitize: Clean the input, e.g. trim whitespace. Directives can hook into this phase by implementing `ArgSanitizerDirective`. @@ -39,8 +37,7 @@ In the given example, Lighthouse will take the value of the `password` argument ## ArgSanitizerDirective -An [`Nuwave\Lighthouse\Support\Contracts\ArgSanitizerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgSanitizerDirective.php) -takes an incoming value and returns a new value. +An [`Nuwave\Lighthouse\Support\Contracts\ArgSanitizerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgSanitizerDirective.php) takes an incoming value and returns a new value. Let's take a look at the built-in [@trim](../api-reference/directives.md#trim) directive. @@ -74,8 +71,8 @@ final class TrimDirective extends BaseDirective implements ArgSanitizerDirective } ``` -The `sanitize` method takes an argument which represents the actual incoming value that is given -to an argument in a query and is expected to modify the value, if needed, and return it. +The `sanitize` method takes an argument which represents the actual incoming value that is given to an argument in a query and is expected to modify the value, if needed. +Return it. For example, if we have the following schema. @@ -106,8 +103,7 @@ final class CreateUser ## ArgTransformerDirective -An [`Nuwave\Lighthouse\Support\Contracts\ArgTransformerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgTransformerDirective.php) -works essentially the same as an [`ArgSanitizerDirective`](#argsanitizerdirective). +An [`Nuwave\Lighthouse\Support\Contracts\ArgTransformerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgTransformerDirective.php) works essentially the same as an [`ArgSanitizerDirective`](#argsanitizerdirective). Notable differences are: - The method to implement is called `transform` @@ -115,9 +111,7 @@ Notable differences are: ## ArgBuilderDirective -An [`Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgBuilderDirective.php) -directive allows using arguments passed by the client to dynamically -modify the database query that Lighthouse creates for a field. +An [`Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgBuilderDirective.php) directive allows using arguments passed by the client to dynamically modify the database query that Lighthouse creates for a field. Currently, the following directives use arguments to modify the query: @@ -139,8 +133,7 @@ type User { } ``` -Passing the `category` argument will select only the user's posts -where the `category` column is equal to the value of the `category` argument. +Passing the `category` argument will select only the user's posts where the `category` column is equal to the value of the `category` argument. So let's take a look at a simplified version of the built-in [@eq](../api-reference/directives.md#eq) directive. @@ -188,8 +181,7 @@ The `handleBuilder` method takes two arguments: - `$value` The value of the argument value that [@eq](../api-reference/directives.md#eq) was applied on to. -If you want to use a more complex value for manipulating a query, -you can build a `ArgBuilderDirective` to work with lists or nested input objects. +If you want to use a more complex value for manipulating a query, you can build a `ArgBuilderDirective` to work with lists or nested input objects. Lighthouse's [@whereBetween](../api-reference/directives.md#wherebetween) is one example of this. ```graphql @@ -206,9 +198,6 @@ input DateRange { ## ArgResolver -An [`Nuwave\Lighthouse\Support\Contracts\ArgResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgResolver.php) -directive allows you to compose resolvers for complex nested inputs, similar to the way -that field resolvers are composed together. +An [`Nuwave\Lighthouse\Support\Contracts\ArgResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgResolver.php) directive allows you to compose resolvers for complex nested inputs, similar to the way that field resolvers are composed together. -For an in-depth explanation of the concept of composing arg resolvers, -read the [explanation of arg resolvers](../concepts/arg-resolvers.md). +For an in-depth explanation of the concept of composing arg resolvers, read the [explanation of arg resolvers](../concepts/arg-resolvers.md). diff --git a/docs/6/custom-directives/type-directives.md b/docs/6/custom-directives/type-directives.md index 4a84dd2182..f562f6b523 100644 --- a/docs/6/custom-directives/type-directives.md +++ b/docs/6/custom-directives/type-directives.md @@ -6,18 +6,15 @@ These directives can generally be applied to [type definitions](../the-basics/ty ## TypeManipulator -The [`Nuwave\Lighthouse\Support\Contracts\TypeManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeManipulator.php) -interface can be used to manipulate the AST from a type definition node. +The [`Nuwave\Lighthouse\Support\Contracts\TypeManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeManipulator.php) interface can be used to manipulate the AST from a type definition node. ## TypeMiddleware -The [`Nuwave\Lighthouse\Support\Contracts\TypeMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeMiddleware.php) -interface allows access to an AST node as it is converted to an executable type. +The [`Nuwave\Lighthouse\Support\Contracts\TypeMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeMiddleware.php) interface allows access to an AST node as it is converted to an executable type. ## TypeResolver -The [`Nuwave\Lighthouse\Support\Contracts\TypeResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeResolver.php) -interface can be used for custom conversion from AST values to an executable type. +The [`Nuwave\Lighthouse\Support\Contracts\TypeResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeResolver.php) interface can be used for custom conversion from AST values to an executable type. ## Type Extension Directives @@ -25,5 +22,4 @@ These directives can generally be applied to [type extensions](https://graphql.g ## TypeExtensionManipulator -The [`Nuwave\Lighthouse\Support\Contracts\TypeExtensionManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeExtensionManipulator.php) -interface can be used to manipulate the AST from a type extension node. +The [`Nuwave\Lighthouse\Support\Contracts\TypeExtensionManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeExtensionManipulator.php) interface can be used to manipulate the AST from a type extension node. diff --git a/docs/6/digging-deeper/adding-types-programmatically.md b/docs/6/digging-deeper/adding-types-programmatically.md index e1965d5eef..80d2a55a61 100644 --- a/docs/6/digging-deeper/adding-types-programmatically.md +++ b/docs/6/digging-deeper/adding-types-programmatically.md @@ -4,9 +4,7 @@ You might want to add additional types to the schema programmatically. ## Additional Schema Definitions -If you want to use the SDL to define additional types dynamically, -you can listen for the [`BuildSchemaString`](../api-reference/events.md#buildschemastring) -event and return additional schema definitions as a string: +If you want to use the SDL to define additional types dynamically, you can listen for the [`BuildSchemaString`](../api-reference/events.md#buildschemastring) event and return additional schema definitions as a string: ```php $dispatcher = app(\Illuminate\Contracts\Events\Dispatcher::class); @@ -18,8 +16,7 @@ $dispatcher->listen( ); ``` -When your schema is defined within files and you want to use `#import` to combine them, -you can use the `Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: +When your schema is defined within files and you want to use `#import` to combine them, you can use the `Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: ```php $stitcher = new \Nuwave\Lighthouse\Schema\Source\SchemaStitcher(__DIR__ . '/path/to/schema.graphql'); @@ -30,11 +27,9 @@ return $stitcher->getSchemaString(); While Lighthouse is an SDL-first GraphQL server, you can also use native PHP type definitions. -Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) -on how to define types. +Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) on how to define types. -Note that you will not have access to a large portion of Lighthouse functionality -that is provided through server-side directives and the definition is much more verbose. +Note that you will not have access to a large portion of Lighthouse functionality that is provided through server-side directives and the definition is much more verbose. Because of this, we do not recommend you use native PHP types for complex object types. diff --git a/docs/6/digging-deeper/client-directives.md b/docs/6/digging-deeper/client-directives.md index 8e45e19ef6..3bf598a75f 100644 --- a/docs/6/digging-deeper/client-directives.md +++ b/docs/6/digging-deeper/client-directives.md @@ -4,17 +4,16 @@ Client directives allow clients to change the behavior of query execution. > Client directives must not be used within your schema definition. -The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) -mentions two client directives: [@skip](#skip) and [@include](#include). +The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) mentions two client directives. +[@skip](#skip) and [@include](#include). Both are built-in to Lighthouse and work out-of-the-box. ## @skip -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional -exclusion during execution as described by the `if` argument. +The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional exclusion during execution as described by the `if` argument. ```graphql directive @skip( @@ -36,11 +35,10 @@ query myQuery($someTest: Boolean) { ## @include -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments, -and allows for conditional inclusion during execution as described by the `if` argument. +The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional inclusion during execution as described by the `if` argument. ```graphql directive @include( @@ -74,19 +72,17 @@ directive @example( ``` By itself, a custom client directive does not do anything. -Lighthouse provides a class to retrieve information about where client directives -were placed in the query and what arguments were given to them. +Lighthouse provides a class to retrieve information about where client directives were placed in the query and what arguments were given to them. ```php $clientDirective = new \Nuwave\Lighthouse\ClientDirectives\ClientDirective('example'); ``` -The most common use case for a client directive is to place it on a field. There is a caveat -to working with this that is unintuitive at first: There might be multiple nodes referencing a single -field, and each of those may or may not have the client directive set, with possibly different arguments. +The most common use case for a client directive is to place it on a field. +There is a caveat to working with this that is unintuitive at first: There might be multiple nodes referencing a single field. +Each of those may or may not have the client directive set, with possibly different arguments. -The following example illustrates how a field `foo` can be referenced three times with different -configurations of a client directive: +The following example illustrates how a field `foo` can be referenced three times with different configurations of a client directive: ```graphql { @@ -98,8 +94,7 @@ configurations of a client directive: } ``` -You can get all arguments for every node that is referencing the field you are currently -resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): +You can get all arguments for every node that is referencing the field you are currently resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): ```php $arguments = $clientDirective->forField($resolveInfo); @@ -116,8 +111,8 @@ For the example query above, it will look like this: ] ``` -You are then free to implement whatever logic on top of that. Some client directives may require -only one field node to have it set, whereas others might require all of them to have the same configuration. +You are then free to implement whatever logic on top of that. +Some client directives may require only one field node to have it set, whereas others might require all of them to have the same configuration. > There are other locations where client directives may be used on: https://spec.graphql.org/draft/#ExecutableDirectiveLocation > You can add a PR to Lighthouse if you need them. diff --git a/docs/6/digging-deeper/deprecation.md b/docs/6/digging-deeper/deprecation.md index 3a51c91688..27bf0d2e96 100644 --- a/docs/6/digging-deeper/deprecation.md +++ b/docs/6/digging-deeper/deprecation.md @@ -1,7 +1,6 @@ # Deprecation -The [@deprecated](../api-reference/directives.md#deprecated) directive allows marking elements -of a GraphQL schema as deprecated. +The [@deprecated](../api-reference/directives.md#deprecated) directive allows marking elements of a GraphQL schema as deprecated. ## Detect deprecated usage @@ -10,8 +9,8 @@ of a GraphQL schema as deprecated. Before you eventually remove deprecated elements, you want to give clients time to switch over. To be sure the elements are no longer in use, dynamic instrumentation is required. -Lighthouse allows you to register a handler function that is called with a list of deprecated -elements that were used in a query. Use a reporting mechanism of your choice to get notified. +Lighthouse allows you to register a handler function that is called with a list of deprecated elements that were used in a query. +Use a reporting mechanism of your choice to get notified. In order to not slow down your response times, use a terminating callback. ```php diff --git a/docs/6/digging-deeper/error-handling.md b/docs/6/digging-deeper/error-handling.md index 2d019500c0..9e8a663c0a 100644 --- a/docs/6/digging-deeper/error-handling.md +++ b/docs/6/digging-deeper/error-handling.md @@ -1,16 +1,15 @@ # Error Handling -Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**, -so you can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). +Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**. +You can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). ## User-friendly Errors -In a production setting, error messages should not be shown to the user by default -to prevent information leaking. In some cases however, you may want to display an -explicit error message to the user. +In a production setting, error messages should not be shown to the user by default to prevent information leaking. +In some cases however, you may want to display an explicit error message to the user. -**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface, that can -be implemented by Exceptions to control how they are rendered to the client. +**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface. +Can be implemented by Exceptions to control how they are rendered to the client. Head over their [Error Handling docs](https://webonyx.github.io/graphql-php/error-handling) to learn more. @@ -18,8 +17,7 @@ Head over their [Error Handling docs](https://webonyx.github.io/graphql-php/erro Lighthouse will catch exceptions thrown during the execution of a query and return them as part of the response. -The error handler `Nuwave\Lighthouse\Execution\ReportingErrorHandler` is included in the default configuration -and reports non-client-safe errors through the default Laravel exception handler. +The error handler `Nuwave\Lighthouse\Execution\ReportingErrorHandler` is included in the default configuration and reports non-client-safe errors through the default Laravel exception handler. Client-safe errors are assumed to be something that: @@ -28,8 +26,7 @@ Client-safe errors are assumed to be something that: Thus, they are typically not actionable for server developers. -However, you can choose to report client-safe errors by replacing `Nuwave\Lighthouse\Execution\ReportingErrorHandler` -with `Nuwave\Lighthouse\Execution\AlwaysReportingErrorHandler` in the `lighthouse.php` config: +However, you can choose to report client-safe errors by replacing `Nuwave\Lighthouse\Execution\ReportingErrorHandler` with `Nuwave\Lighthouse\Execution\AlwaysReportingErrorHandler` in the `lighthouse.php` config: ```diff 'error_handlers' => [ @@ -42,8 +39,7 @@ with `Nuwave\Lighthouse\Execution\AlwaysReportingErrorHandler` in the `lighthous ## Additional Error Information -The interface [`GraphQL\Error\ProvidesExtensions`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ProvidesExtensions.php) -may be implemented to add more information than just an error message to the rendered error output. +The interface [`GraphQL\Error\ProvidesExtensions`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ProvidesExtensions.php) may be implemented to add more information than just an error message to the rendered error output. This custom exception contains information about the reason the exception was thrown: @@ -89,8 +85,7 @@ final class CustomException extends Exception implements ClientAware, ProvidesEx } ``` -Now you can throw that Exception somewhere in your code, for example in your resolver, -and it will display additional error output. +Now you can throw that Exception somewhere in your code, for example in your resolver, and it will display additional error output. ```php namespace App\GraphQL\Queries; @@ -174,11 +169,9 @@ final class CountErrorHandler implements ErrorHandler ## Partial Errors -As a GraphQL query may return a partial result, you may not always want to abort -execution immediately after an error occurred. +As a GraphQL query may return a partial result, you may not always want to abort execution immediately after an error occurred. -Use the [`ErrorPool`](https://github.com/nuwave/lighthouse/blob/master/src/Execution/ErrorPool.php) -when you want to collect multiple errors before returning a result. +Use the [`ErrorPool`](https://github.com/nuwave/lighthouse/blob/master/src/Execution/ErrorPool.php) when you want to collect multiple errors before returning a result. ```php try { diff --git a/docs/6/digging-deeper/extending-lighthouse.md b/docs/6/digging-deeper/extending-lighthouse.md index 5bbc66bef2..0b4aa5e4e8 100644 --- a/docs/6/digging-deeper/extending-lighthouse.md +++ b/docs/6/digging-deeper/extending-lighthouse.md @@ -4,8 +4,7 @@ Lighthouse offers various extension points which can be used by package and appl ## The Event System -Lighthouse offers a unified way of hooking into the complete execution lifecycle -through [Laravel's event system](https://laravel.com/docs/events). +Lighthouse offers a unified way of hooking into the complete execution lifecycle through [Laravel's event system](https://laravel.com/docs/events). You may use any Service Provider to register listeners. A complete list of all dispatched events is available [in the events API reference](../api-reference/events.md). @@ -35,8 +34,7 @@ final class SomePackageServiceProvider extends ServiceProvider ## Changing the default resolver -Lighthouse will fall back to using [webonyx's default resolver](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver) -for non-root fields, [see resolver precedence](../the-basics/fields.md#resolver-precedence). +Lighthouse will fall back to using [webonyx's default resolver](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver) for non-root fields, [see resolver precedence](../the-basics/fields.md#resolver-precedence). You may override this by calling `GraphQL\Executor\Executor::setDefaultFieldResolver()` in your service provider's `boot()` method. @@ -44,8 +42,7 @@ You may override this by calling `GraphQL\Executor\Executor::setDefaultFieldReso The context is the third argument of any resolver function. -You may replace the default `Nuwave\Lighthouse\Schema\Context` with your own -implementation of the interface `Nuwave\Lighthouse\Support\Contracts\GraphQLContext`. +You may replace the default `Nuwave\Lighthouse\Schema\Context` with your own implementation of the interface `Nuwave\Lighthouse\Support\Contracts\GraphQLContext`. The following example is just a starting point of what you can do: ```php diff --git a/docs/6/digging-deeper/feature-toggles.md b/docs/6/digging-deeper/feature-toggles.md index fe4e56587e..578ea8bdbe 100644 --- a/docs/6/digging-deeper/feature-toggles.md +++ b/docs/6/digging-deeper/feature-toggles.md @@ -4,11 +4,10 @@ Lighthouse allows you to conditionally show or hide elements (fields, types, arg ## @show and @hide -The directives [@show](../api-reference/directives.md#show) and [@hide](../api-reference/directives.md#hide) -work in a similar way, but are logical opposites of each other. +The directives [@show](../api-reference/directives.md#show) and [@hide](../api-reference/directives.md#hide) work in a similar way. +Are logical opposites of each other. -For example, you might want to limit an experimental new field to test environments. -[@show](../api-reference/directives.md#show) is most suitable for this: +For example, you might want to limit an experimental new field to test environments. [@show](../api-reference/directives.md#show) is most suitable for this: ```graphql type Query { @@ -27,8 +26,7 @@ type Query { ## @feature -The [@feature](../api-reference/directives.md#feature) directive allows to include fields, types, arguments, or input fields in the schema -depending on whether a [Laravel Pennant](https://laravel.com/docs/pennant) feature is active. +The [@feature](../api-reference/directives.md#feature) directive allows to include fields, types, arguments, or input fields in the schema depending on whether a [Laravel Pennant](https://laravel.com/docs/pennant) feature is active. For example, you might want a new experimental field only to be available when the according feature is active: @@ -48,8 +46,7 @@ type Query { } ``` -When using [class based features](https://laravel.com/docs/pennant#class-based-features), -the fully qualified class name must be used as the value for the `name` argument: +When using [class based features](https://laravel.com/docs/pennant#class-based-features), the fully qualified class name must be used as the value for the `name` argument: ```graphql type Query { @@ -59,8 +56,7 @@ type Query { ## Conditional Type Inclusion -When you conditionally include a type using [@show](../api-reference/directives.md#show), [@hide](../api-reference/directives.md#hide) or [@feature](../api-reference/directives.md#feature), -any fields using it must also be conditionally included. +When you conditionally include a type using [@show](../api-reference/directives.md#show), [@hide](../api-reference/directives.md#hide) or [@feature](../api-reference/directives.md#feature), any fields using it must also be conditionally included. If the type is omitted but still used somewhere, the schema will be invalid. ```graphql @@ -76,11 +72,9 @@ type Query { ## Interaction With Schema Cache [@show](../api-reference/directives.md#show) and [@hide](../api-reference/directives.md#hide) work by manipulating the schema. -This means that when using their `env` option, the inclusion or exclusion of elements depends on the value -of `app()->environment()` at the time the schema is built and not update on later environment changes. +This means that when using their `env` option, the inclusion or exclusion of elements depends on the value of `app()->environment()` at the time the schema is built and not update on later environment changes. If you are pre-generating your schema cache, make sure to match the environment to your deployment target. -The same goes for [@feature](../api-reference/directives.md#feature). Whether a field is included in the schema will be -based on the state of a feature at the time the schema is built. In addition, if you are pre-generating your schema cache, -you will only be able to use features that support [nullable scopes](https://laravel.com/docs/pennant#nullable-scope), -as there won't be an authenticated user to check the feature against. +The same goes for [@feature](../api-reference/directives.md#feature). +Whether a field is included in the schema will be based on the state of a feature at the time the schema is built. +In addition, if you are pre-generating your schema cache, you will only be able to use features that support [nullable scopes](https://laravel.com/docs/pennant#nullable-scope), as there won't be an authenticated user to check the feature against. diff --git a/docs/6/digging-deeper/file-uploads.md b/docs/6/digging-deeper/file-uploads.md index bfafc1179f..b881ca9d81 100644 --- a/docs/6/digging-deeper/file-uploads.md +++ b/docs/6/digging-deeper/file-uploads.md @@ -1,7 +1,6 @@ # Uploading files -Lighthouse allows you to upload files using a multipart form request -as defined in [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec). +Lighthouse allows you to upload files using a multipart form request as defined in [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec). ## Setup @@ -25,11 +24,9 @@ type Mutation { ## Handling file uploads Lighthouse accepts multipart form requests that contain file uploads. -The given file is injected into the `array $variables` as an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) -and passed into the resolver. +The given file is injected into the `array $variables` as an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) and passed into the resolver. -It is up to you how to handle the given file in the resolver, -see the [Laravel docs for File Uploads](https://laravel.com/docs/filesystem#file-uploads). +It is up to you how to handle the given file in the resolver, see the [Laravel docs for File Uploads](https://laravel.com/docs/filesystem#file-uploads). The field from the previous example can be implemented like this: @@ -56,8 +53,7 @@ final class Upload ## Client-side Usage In order to upload a file, you must send a `multipart/form-data` request. -Use any of the [available client implementations](https://github.com/jaydenseric/graphql-multipart-request-spec#client) -or look at the [specification examples](https://github.com/jaydenseric/graphql-multipart-request-spec#multipart-form-field-structure) to roll your own. +Use any of the [available client implementations](https://github.com/jaydenseric/graphql-multipart-request-spec#client) or look at the [specification examples](https://github.com/jaydenseric/graphql-multipart-request-spec#multipart-form-field-structure) to roll your own. > If you are using [the EnsureXHR middleware to protect against CSRF](../security/csrf.md), > add the header `X-Requested-With: XMLHttpRequest` to your request. diff --git a/docs/6/digging-deeper/ordering.md b/docs/6/digging-deeper/ordering.md index 175141ef5a..5c9819882b 100644 --- a/docs/6/digging-deeper/ordering.md +++ b/docs/6/digging-deeper/ordering.md @@ -2,8 +2,7 @@ ## Client Controlled Ordering -To enable clients to control the ordering, use [@orderBy](../api-reference/directives.md#orderby) on an argument of -a field that is backed by a database query. +To enable clients to control the ordering, use [@orderBy](../api-reference/directives.md#orderby) on an argument of a field that is backed by a database query. ```graphql type Query { @@ -11,9 +10,8 @@ type Query { } ``` -The type of the argument can be left blank as `_` , -as Lighthouse will automatically generate an input that takes enumerated column names, -together with the `SortOrder` enum, and add that to your schema: +The type of the argument can be left blank as `_` , as Lighthouse will automatically generate an input that takes enumerated column names, together with the `SortOrder` enum. +Add that to your schema: ```graphql "Order by clause for Query.posts.orderBy." diff --git a/docs/6/digging-deeper/relay.md b/docs/6/digging-deeper/relay.md index c9811ac345..e5432abb3d 100644 --- a/docs/6/digging-deeper/relay.md +++ b/docs/6/digging-deeper/relay.md @@ -2,9 +2,7 @@ ## Cursor Connection -Relay requires a particular kind of pagination which is the [Cursor Connection](https://facebook.github.io/relay/graphql/connections.htm) -To get a relay-compatible connection on a root query field, use the [@paginate](../api-reference/directives.md#paginate) -directive with the pagination type `CONNECTION`. +Relay requires a particular kind of pagination which is the [Cursor Connection](https://facebook.github.io/relay/graphql/connections.htm) To get a relay-compatible connection on a root query field, use the [@paginate](../api-reference/directives.md#paginate) directive with the pagination type `CONNECTION`. > Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -15,11 +13,10 @@ type Query { } ``` -This automatically converts the type definition into a relay connection and constructs -the appropriate queries via the underlying Eloquent model. +This automatically converts the type definition into a relay connection and constructs the appropriate queries via the underlying Eloquent model. -Connections can also be used for subfields of a type, given they are defined as a HasMany-Relationship -in Eloquent. Use the [@hasMany](../api-reference/directives.md#hasmany) directive. +Connections can also be used for subfields of a type, given they are defined as a HasMany-Relationship in Eloquent. +Use the [@hasMany](../api-reference/directives.md#hasmany) directive. ```graphql type User { @@ -30,8 +27,7 @@ type User { ## Global Object Identification -You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global IDs. +You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global IDs. [Global Object Identification](https://relay.dev/graphql/objectidentification.htm) diff --git a/docs/6/digging-deeper/schema-organisation.md b/docs/6/digging-deeper/schema-organisation.md index fc97d49851..07598310b0 100644 --- a/docs/6/digging-deeper/schema-organisation.md +++ b/docs/6/digging-deeper/schema-organisation.md @@ -45,8 +45,7 @@ graphql/ |-- category.graphql ``` -To import all schema files in `blog/` in one go, use wildcard import syntax -(works like PHP's [glob function](https://php.net/manual/function.glob.php)). +To import all schema files in `blog/` in one go, use wildcard import syntax (works like PHP's [glob function](https://php.net/manual/function.glob.php)). ```graphql #import blog/*.graphql @@ -70,11 +69,10 @@ The definition is imported from `schema.graphql`: ``` Now you want to add queries to allow fetching posts. -While you could add it to the main `Query` type in `schema.graphql`, -it is generally preferable to colocate queries with the type they return. +While you could add it to the main `Query` type in `schema.graphql`, it is generally preferable to colocate queries with the type they return. -Make sure `schema.graphql` contains a `Query` type. You can add an empty type -if you don't have one there: +Make sure `schema.graphql` contains a `Query` type. +You can add an empty type if you don't have one there: ```graphql type Query @@ -95,5 +93,4 @@ extend type Query { The fields in the `extend type` definition are merged with those of the original type. Apart from object types `type`, you can also extend `input`, `interface` and `enum` types. -Lighthouse will merge the fields (or values) with the original definition and always -produce a single type in the final schema. +Lighthouse will merge the fields (or values) with the original definition and always produce a single type in the final schema. diff --git a/docs/6/eloquent/complex-where-conditions.md b/docs/6/eloquent/complex-where-conditions.md index 4c6579b506..b45538e493 100644 --- a/docs/6/eloquent/complex-where-conditions.md +++ b/docs/6/eloquent/complex-where-conditions.md @@ -2,10 +2,8 @@ **Experimental: not enabled by default, not guaranteed to be stable.** -Adding query conditions ad-hoc can be cumbersome and limiting when you require -manifold ways to filter query results. -Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients -and allow them to apply complex, dynamic WHERE conditions to queries. +Adding query conditions ad-hoc can be cumbersome and limiting when you require manifold ways to filter query results. +Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients and allow them to apply complex, dynamic WHERE conditions to queries. ## Setup @@ -18,8 +16,7 @@ return [ ] ``` -For other versions, register the service provider `Nuwave\Lighthouse\WhereConditions\WhereConditionsServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +For other versions, register the service provider `Nuwave\Lighthouse\WhereConditions\WhereConditionsServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). Install the dependency [mll-lab/graphql-php-scalars](https://github.com/mll-lab/graphql-php-scalars): @@ -29,8 +26,7 @@ composer require mll-lab/graphql-php-scalars ## Usage -You can use this feature through a set of schema directives that enhance fields -with advanced filter capabilities. +You can use this feature through a set of schema directives that enhance fields with advanced filter capabilities. ### @whereConditions @@ -89,8 +85,8 @@ type Person { } ``` -Lighthouse automatically generates definitions for an `Enum` type and an `Input` type -that are restricted to the defined columns, so you do not have to specify them by hand. +Lighthouse automatically generates definitions for an `Enum` type and an `Input` type that are restricted to the defined columns. +You do not have to specify them by hand. The blank type named `_` will be changed to the actual type. Here are the types that will be included in the compiled schema: @@ -140,8 +136,8 @@ input QueryPeopleWhereWhereConditionsRelation { } ``` -Alternatively to the `columns` argument, you can also use `columnsEnum` in case you -want to re-use a list of allowed columns. Here's how your schema could look like: +Alternatively to the `columns` argument, you can also use `columnsEnum` in case you want to re-use a list of allowed columns. +Here's how your schema could look like: ```graphql type Query { @@ -167,8 +163,7 @@ Instead of creating enums for the allowed columns, it will simply use the existi It is recommended to either use the `columns` or the `columnsEnum` argument. When you don't define any allowed columns, clients can specify arbitrary column names as a `String`. -This approach should by taken with care, as it carries -potential performance and security risks and offers little type safety. +This approach should by taken with care, as it carries potential performance and security risks and offers little type safety. A simple query for a person who is exactly 42 years old would look like this: @@ -180,8 +175,7 @@ A simple query for a person who is exactly 42 years old would look like this: } ``` -Note that the operator defaults to `EQ` (`=`) if not given, so you could -also omit it from the previous example and get the same result. +Note that the operator defaults to `EQ` (`=`) if not given, so you could also omit it from the previous example and get the same result. The following query gets actors over age 37 who either have red hair or are at least 150cm: @@ -206,8 +200,8 @@ The following query gets actors over age 37 who either have red hair or are at l } ``` -Some operators require passing lists of values - or no value at all. The following -query gets people that have no hair and blue-ish eyes: +Some operators require passing lists of values - or no value at all. +The following query gets people that have no hair and blue-ish eyes: ```graphql { @@ -281,8 +275,7 @@ directive @whereHasConditions( ) on ARGUMENT_DEFINITION ``` -This directive works very similar to [@whereConditions](#whereconditions), except that -the conditions are applied to a relation sub query: +This directive works very similar to [@whereConditions](#whereconditions), except that the conditions are applied to a relation sub query: ```graphql type Query { @@ -325,8 +318,7 @@ enum QueryPeopleHasRoleColumn { } ``` -A simple query for a person who has an access level of at least 5, through one of -their roles, looks like this: +A simple query for a person who has an access level of at least 5, through one of their roles, looks like this: ```graphql { @@ -361,10 +353,10 @@ This query would retrieve all persons, no matter if they have a role or not: ## Custom operator If Lighthouse's default `SQLOperator` does not fit your use case, you can register a custom operator class. -This may be necessary if your database uses different SQL operators then Lighthouse's default, -or you want to extend/restrict the allowed operators. +This may be necessary if your database uses different SQL operators then Lighthouse's default, or you want to extend/restrict the allowed operators. -First create a class that implements `Nuwave\Lighthouse\WhereConditions\Operator`. For example: +First create a class that implements `Nuwave\Lighthouse\WhereConditions\Operator`. +For example: ```php namespace App\GraphQL; @@ -407,9 +399,8 @@ Make sure to add it after Lighthouse's service provider: ## Custom handler -If you want to take advantage of the schema generation that [@whereConditions](#whereconditions) -and [@whereHasConditions](#wherehasconditions) provide, but customize the application of arguments -to the query builder, you can provide a custom handler. +If you want to take advantage of the schema generation that [@whereConditions](#whereconditions) and [@whereHasConditions](#wherehasconditions) provide. +Customize the application of arguments to the query builder, you can provide a custom handler. ```graphql type Query { @@ -419,8 +410,7 @@ type Query { } ``` -When a client passes `where`, your handler will be called with the query builder and -the passed conditions: +When a client passes `where`, your handler will be called with the query builder and the passed conditions: ```php namespace App; diff --git a/docs/6/eloquent/getting-started.md b/docs/6/eloquent/getting-started.md index 9b58e3bade..a146d4bbfc 100644 --- a/docs/6/eloquent/getting-started.md +++ b/docs/6/eloquent/getting-started.md @@ -26,8 +26,7 @@ type Query { } ``` -The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as -the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. +The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. The following query: @@ -55,8 +54,7 @@ Will return the following result: ## Pagination -You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to -query a large list of models in chunks. +You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to query a large list of models in chunks. ```graphql type Query { @@ -96,8 +94,7 @@ And can be queried like this: ## Adding Query Constraints -Lighthouse provides directives such as [@eq](../api-reference/directives.md#eq) -to enhance your queries with additional constraints. +Lighthouse provides directives such as [@eq](../api-reference/directives.md#eq) to enhance your queries with additional constraints. The following field definition allows clients to find a user by their email: @@ -133,13 +130,11 @@ If found, the result will look like this: ## Ordering -Use the [@orderBy](../api-reference/directives.md#orderby) directive to sort -a result list by one or more given columns. +Use the [@orderBy](../api-reference/directives.md#orderby) directive to sort a result list by one or more given columns. ## Local Scopes -[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models -to specify reusable query constraints. +[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models to specify reusable query constraints. ```php use Illuminate\Database\Eloquent\Builder; @@ -154,8 +149,7 @@ final class User extends Model } ``` -Directives that query models, such as [@all](../api-reference/directives.md#all) -or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: +Directives that query models, such as [@all](../api-reference/directives.md#all) or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: ```graphql type Query { @@ -215,7 +209,7 @@ type Mutation { } ``` -Since GraphQL allows you to update just parts of your data, it is best to have all arguments except `id` as optional. +Because GraphQL allows partial updates, it is best to keep all arguments optional except `id`. ```graphql mutation { @@ -251,8 +245,7 @@ To update multiple models at once, use the [@updateMany](../api-reference/direct ## Upsert -Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with -a given `id` or create it if it does not exist. +Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with a given `id` or create it if it does not exist. ```graphql type Mutation { @@ -288,7 +281,8 @@ To upsert multiple models at once, use the [@upsertMany](../api-reference/direct ## Delete -Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. Dangerously easy. +Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. +Dangerously easy. ```graphql type Mutation { @@ -306,7 +300,8 @@ mutation { } ``` -This mutation will return the deleted object, so you will have a last chance to look at the data. Use it wisely. +This mutation will return the deleted object, so you will have a last chance to look at the data. +Use it wisely. ```json { diff --git a/docs/6/eloquent/nested-mutations.md b/docs/6/eloquent/nested-mutations.md index 08659dbfc8..c3beaa8455 100644 --- a/docs/6/eloquent/nested-mutations.md +++ b/docs/6/eloquent/nested-mutations.md @@ -1,12 +1,11 @@ # Nested Mutations -Lighthouse allows you to create, update or delete models and their associated relationships, -all in one single mutation. This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). +Lighthouse allows you to create, update or delete models and their associated relationships, all in one single mutation. +This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). ## Return Types Required -You have to define return types on your relationship methods so that Lighthouse -can detect them. +You have to define return types on your relationship methods so that Lighthouse can detect them. ```php use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -28,20 +27,17 @@ final class Post extends Model ## Partial Failure By default, all mutations are wrapped in a database transaction. -If any of the nested operations fail, the whole mutation is aborted -and no changes are written to the database. +If any of the nested operations fail, the whole mutation is aborted and no changes are written to the database. You can change this setting [in the configuration](../getting-started/configuration.md). ## Polymorphic Relation Limitations -Because the GraphQL Specification does not support polymorphic Input types (yet), -the available functionality is limited. +Because the GraphQL Specification does not support polymorphic Input types (yet), the available functionality is limited. -It is not possible to have an argument that can contain different types, which -would be necessary to pass the attributes the different related models might have. -For now, we can only support cases where the input type does not change across related -models, e.g. connecting through an ID, disconnecting or deleting the relation. +It is not possible to have an argument that can contain different types. +Would be necessary to pass the attributes the different related models might have. +For now, we can only support cases where the input type does not change across related models, e.g. connecting through an ID, disconnecting or deleting the relation. See [this issue](https://github.com/nuwave/lighthouse/issues/900) for further discussion. @@ -50,8 +46,7 @@ See [this issue](https://github.com/nuwave/lighthouse/issues/900) for further di Lighthouse has no mechanism for fine-grained permissions of nested mutation operations. Field directives such as the [@can\* family of directives](../api-reference/directives.md#can-family-of-directives) apply to the whole field. -Make sure that fields with nested mutations are only available to users who are allowed -to execute all reachable nested mutations. +Make sure that fields with nested mutations are only available to users who are allowed to execute all reachable nested mutations. ## BelongsTo @@ -63,8 +58,7 @@ type Mutation { } ``` -The mutation takes a single argument `input` that contains data about -the Post you want to create. +The mutation takes a single argument `input` that contains data about the Post you want to create. ```graphql input CreatePostInput { @@ -73,8 +67,7 @@ input CreatePostInput { } ``` -The first argument `title` is a value of the `Post` itself and corresponds -to a column in the database. +The first argument `title` is a value of the `Post` itself and corresponds to a column in the database. The second argument `author` is named just like the relationship method that is defined on the `Post` model. A nested `BelongsTo` relationship exposes the following operations: @@ -135,8 +128,7 @@ Lighthouse will create a new `Post` and associate an `User` with it. } ``` -If the related model does not exist yet, you can also -create a new one. +If the related model does not exist yet, you can also create a new one. ```graphql mutation { @@ -165,8 +157,8 @@ mutation { ``` When issuing an update, you can also allow the user to remove a relation. -Both `disconnect` and `delete` remove the association to the author, -but `delete` also removes the author model itself. +Both `disconnect` and `delete` remove the association to the author. +`delete` also removes the author model itself. ```graphql type Mutation { @@ -190,8 +182,7 @@ input UpdateUserBelongsTo { ``` You must pass a truthy value to `disconnect` and `delete` for them to actually run. -This structure was chosen as it is consistent with updating `BelongsToMany` relationships -and allows the query string to be mostly static, taking a variable value to control its behavior. +This structure was chosen as it is consistent with updating `BelongsToMany` relationships and allows the query string to be mostly static, taking a variable value to control its behavior. ```graphql mutation UpdatePost($disconnectAuthor: Boolean) { @@ -210,8 +201,8 @@ mutation UpdatePost($disconnectAuthor: Boolean) { } ``` -The `author` relationship will only be disconnected if the value of the variable -`$disconnectAuthor` is `true`, if `false` or `null` are passed, it will not change. +The `author` relationship is disconnected only when `$disconnectAuthor` is `true`. +If `false` or `null` is passed, it will not change. ```json { @@ -260,9 +251,7 @@ mutation UpdatePost($disconnectAuthor: Boolean) { ## MorphTo -The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), -the main difference being that the `connect` operation requires an input type with both -the `id` and `type` of the related model. +The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), the main difference being that the `connect` operation requires an input type with both the `id` and `type` of the related model. ```graphql type Task { @@ -367,8 +356,8 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Phone` model. +This mutation takes a single `input` argument. +It contains values of the `User` and its associated `Phone` model. ```graphql input UpdateUserInput { @@ -434,8 +423,8 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Post` models. +This mutation takes a single `input` argument. +It contains values of the `User` and its associated `Post` models. ```graphql input CreateUserInput { @@ -444,8 +433,7 @@ input CreateUserInput { } ``` -Now, we can expose an operation that allows us to directly create new posts -right when we create the `User`. +Now, we can expose an operation that allows us to directly create new posts right when we create the `User`. ```graphql input CreatePostsHasMany { @@ -561,8 +549,7 @@ mutation { } ``` -The behavior for `upsert` is a mix between updating and creating, -it will produce the needed action regardless of whether the model exists or not. +The behavior for `upsert` is a mix between updating and creating, it will produce the needed action regardless of whether the model exists or not. ## MorphMany @@ -570,8 +557,7 @@ Works exactly like [Has Many](#hasmany). ## BelongsToMany -A belongs to many relation allows you to create new related models as well -as attaching existing ones. +A belongs to many relation allows you to create new related models as well as attaching existing ones. ```graphql type Mutation { @@ -648,8 +634,7 @@ Lighthouse will detect the relationship and attach, update or create it. } ``` -It is also possible to use the `sync` operation to ensure only the given IDs -will be contained within the relation. +It is also possible to use the `sync` operation to ensure only the given IDs will be contained within the relation. ```graphql mutation { @@ -680,8 +665,8 @@ input UpdateAuthorBelongsToMany { ### Storing Pivot Data It is common that many-to-many relations store some extra data in pivot tables. -Suppose we want to track what movies a user has seen. In addition to connecting -the two entities, we want to store how well they liked it: +Suppose we want to track what movies a user has seen. +In addition to connecting the two entities, we want to store how well they liked it: ```graphql type User { @@ -700,13 +685,11 @@ type UserMoviePivot { } ``` -Laravel's `sync()`, `syncWithoutDetach()` or `connect()` methods allow you to pass -an array where the keys are IDs of related models and the values are pivot data. +Laravel's `sync()`, `syncWithoutDetach()` or `connect()` methods allow you to pass an array where the keys are IDs of related models and the values are pivot data. Lighthouse exposes this capability through the nested operations on many-to-many relations. Instead of passing just a list of IDs, you can define an `input` type that also contains pivot data. -It must contain a field called `id` to contain the ID of the related model, -all other fields will be inserted into the pivot table. +It must contain a field called `id` to contain the ID of the related model, all other fields will be inserted into the pivot table. ```graphql type Mutation { diff --git a/docs/6/eloquent/polymorphic-relationships.md b/docs/6/eloquent/polymorphic-relationships.md index fc8ea0cd5b..ef5de1f768 100644 --- a/docs/6/eloquent/polymorphic-relationships.md +++ b/docs/6/eloquent/polymorphic-relationships.md @@ -27,8 +27,7 @@ type Image { ``` First, let's go ahead and add the relations to `Image` since they are straightforward. -The field name should match your relationship method name and be annotated -with the [@morphOne](../api-reference/directives.md#morphone) directive. +The field name should match your relationship method name and be annotated with the [@morphOne](../api-reference/directives.md#morphone) directive. ```graphql type Post { @@ -44,20 +43,17 @@ type User { } ``` -Depending on the rules of your application, you might require the relationship -to be there in some cases, while allowing it to be absent in others. In this -example, a `Post` must always have an `Image`, while a `User` does not require one. +Depending on the rules of your application, you might require the relationship to be there in some cases, while allowing it to be absent in others. +In this example, a `Post` must always have an `Image`, while a `User` does not require one. -For the inverse, you will need to define a [union type](../the-basics/types.md#union) -to express that an `Image` might be linked to different models. +For the inverse, you will need to define a [union type](../the-basics/types.md#union) to express that an `Image` might be linked to different models. ```graphql union Imageable = Post | User ``` Now, reference the union type from a field in your `Image` type. -You can use the [@morphTo](../api-reference/directives.md#morphto) directive -for performance optimization. +You can use the [@morphTo](../api-reference/directives.md#morphto) directive for performance optimization. ```graphql type Image { @@ -67,8 +63,8 @@ type Image { } ``` -The default type resolver will be able to determine which concrete object type is returned -when dealing with Eloquent models, so your definition should just work. +The default type resolver will be able to determine which concrete object type is returned when dealing with Eloquent models. +Your definition should just work. Given you have a field `images` that returns a list of `[Image!]!`, you could query it like this: @@ -90,10 +86,8 @@ Given you have a field `images` that returns a list of `[Image!]!`, you could qu ## One to Many -Based on the above example, you could change your application to allow -for a `Post` to have many images attached to it. -The field `images` now returns a list of `Image` object and is annotated -with the [@morphMany](../api-reference/directives.md#morphmany) directive. +Based on the above example, you could change your application to allow for a `Post` to have many images attached to it. +The field `images` now returns a list of `Image` object and is annotated with the [@morphMany](../api-reference/directives.md#morphmany) directive. ```graphql type Post { diff --git a/docs/6/eloquent/relationships.md b/docs/6/eloquent/relationships.md index ef05d66df9..5081351649 100644 --- a/docs/6/eloquent/relationships.md +++ b/docs/6/eloquent/relationships.md @@ -34,19 +34,17 @@ type Post { } ``` -Because Laravel relationships can be accessed just like regular properties on your model, -the default field resolver will work just fine. +Because Laravel relationships can be accessed just like regular properties on your model, the default field resolver will work just fine. ## Avoiding the N+1 performance problem When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. -This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: -the so-called N+1 query problem. [Learn more](../performance/n-plus-one.md). +This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: the so-called N+1 query problem. +[Learn more](../performance/n-plus-one.md). -When you decorate your relationship fields with Lighthouse's built-in relationship -directives, queries are automatically combined through a technique called _batch loading_. +When you decorate your relationship fields with Lighthouse's built-in relationship directives, queries are automatically combined through a technique called _batch loading_. That means you get fewer database requests and better performance without doing much work. > Batch loading might not provide ideal performance for all use cases. You can turn @@ -54,8 +52,7 @@ That means you get fewer database requests and better performance without doing ## One To One -Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) -between two types in your schema. +Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) between two types in your schema. ```graphql type User { @@ -91,8 +88,7 @@ type Comment { ## Many To Many -While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) -are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. +While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. Use the [@belongsToMany](../api-reference/directives.md#belongstomany) directive to define it. ```graphql @@ -131,9 +127,8 @@ type Project { ## Renaming relations -When you define a relation, Lighthouse assumes that the field and the relationship -method have the same name. If you need to name your field differently, you have to -specify the name of the method. +When you define a relation, Lighthouse assumes that the field and the relationship method have the same name. +If you need to name your field differently, you have to specify the name of the method. ```graphql type Post { diff --git a/docs/6/eloquent/soft-deleting.md b/docs/6/eloquent/soft-deleting.md index 742b23a1fb..3aa201488a 100644 --- a/docs/6/eloquent/soft-deleting.md +++ b/docs/6/eloquent/soft-deleting.md @@ -4,9 +4,7 @@ Lighthouse offers convenient helpers to work with models that use [soft deletes] ## Filter Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field -to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. ```graphql type Query { @@ -14,8 +12,7 @@ type Query { } ``` -Lighthouse will automatically add an argument `trashed` to the field definition -and include the enum `Trashed`. +Lighthouse will automatically add an argument `trashed` to the field definition and include the enum `Trashed`. ```graphql type Query { @@ -44,8 +41,7 @@ You can include soft deleted models in your result with a query like this: ## Restoring Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. ```graphql type Mutation { @@ -67,8 +63,7 @@ This mutation will return the restored object. ## Permanently Deleting Models -To truly remove a model from the database, -use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. +To truly remove a model from the database, use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. Your model must use the `Illuminate\Database\Eloquent\SoftDeletes` trait. ```graphql diff --git a/docs/6/federation/entities.md b/docs/6/federation/entities.md index fa5be6a80f..dd0da3499c 100644 --- a/docs/6/federation/entities.md +++ b/docs/6/federation/entities.md @@ -1,11 +1,9 @@ # Entities A core component of a federation capable GraphQL service is the `_entities` field. -For a given `__typename` in the given `$representations`, Lighthouse will look for -a [reference resolver](reference-resolvers.md) to return the full `_Entity`. +For a given `__typename` in the given `$representations`, Lighthouse will look for a [reference resolver](reference-resolvers.md) to return the full `_Entity`. ## Extends You have to use `@extends` in place of `extend type` to annotate type references. -This is because Lighthouse merges type extensions before the final schema is produced, -thus they would not be preserved to appear in the federation schema SDL. +This is because Lighthouse merges type extensions before the final schema is produced, thus they would not be preserved to appear in the federation schema SDL. diff --git a/docs/6/federation/entity-representations.md b/docs/6/federation/entity-representations.md index 0edf4984ae..e62f4346fc 100644 --- a/docs/6/federation/entity-representations.md +++ b/docs/6/federation/entity-representations.md @@ -29,13 +29,15 @@ type Comment @extends @key(fields: "id") { ## Non-Eloquent representation If entities don't have an Eloquent relationship within the subgraph, it's necessary to specify a separate resolver that will return the required information. -The resolver should return data containing information about the `__typename` field, which corresponds to the entity's name and the primary key that can identify the entity. +The resolver should return data containing information about the `__typename` field. +Corresponds to the entity's name and the primary key that can identify the entity. The `__typename` can either be provided as an explicit field or implicitly by returning an object with a matching class name. ### Example 1 -In this example, subgraph for order service has an entity called `Order`, which in turn has an entity called `Receipt` -defined in a separate subgraph for payment service. The relationship between `Order` and `Receipt` is one-to-one. +In this example, subgraph for order service has an entity called `Order`. +In turn has an entity called `Receipt` defined in a separate subgraph for payment service. +The relationship between `Order` and `Receipt` is one-to-one. ```graphql type Order { @@ -70,8 +72,9 @@ final class Receipt ### Example 2 -In this example, subgraph for order service has an entity called `Order`, which in turn has an entity called `Product` -defined in a separate subgraph for product service. The relationship between `Order` and `Product` is one-to-many. +In this example, subgraph for order service has an entity called `Order`. +In turn has an entity called `Product` defined in a separate subgraph for product service. +The relationship between `Order` and `Product` is one-to-many. ```graphql type Order { @@ -84,7 +87,8 @@ type Product @extends @key(fields: "uuid") { } ``` -The resolver for product in order service returns an array of arrays. Each sub-array consists of: +The resolver for product in order service returns an array of arrays. +Each sub-array consists of: - `__typename` - the entity name from the product service; - `uuid` - the primary key of a specific product. diff --git a/docs/6/federation/getting-started.md b/docs/6/federation/getting-started.md index 7bdd8da33e..9074497dc4 100644 --- a/docs/6/federation/getting-started.md +++ b/docs/6/federation/getting-started.md @@ -10,8 +10,7 @@ It can not serve as a [federation gateway](https://www.apollographql.com/docs/fe ## Setup -Register the service provider `Nuwave\Lighthouse\Federation\FederationServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Federation\FederationServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## Publishing Your Schema @@ -48,8 +47,7 @@ extend schema ## Federated tracing -In order to use federated tracing, you need to enabled [tracing](../performance/tracing.md) -and set the driver to `Nuwave\Lighthouse\Tracing\FederatedTracing\FederatedTracing::class` in your `config/lighthouse.php`: +In order to use federated tracing, you need to enabled [tracing](../performance/tracing.md) and set the driver to `Nuwave\Lighthouse\Tracing\FederatedTracing\FederatedTracing::class` in your `config/lighthouse.php`: ```php 'tracing' => [ diff --git a/docs/6/federation/reference-resolvers.md b/docs/6/federation/reference-resolvers.md index d64f34b372..c2703f0806 100644 --- a/docs/6/federation/reference-resolvers.md +++ b/docs/6/federation/reference-resolvers.md @@ -4,11 +4,9 @@ To enable the current subgraph to provide entities for other subgraphs, you need These reference resolvers act as helpers to enable cross-subgraph communication and provide data from one subgraph to another when needed. Read more about reference resolvers in the [Apollo Federation docs](https://www.apollographql.com/docs/federation/v1/entities#reference-resolvers). -Lighthouse will look for a class which name is equivalent to `__typename` in the -namespace configured in `lighthouse.federation.entities_resolver_namespace`. +Lighthouse will look for a class which name is equivalent to `__typename` in the namespace configured in `lighthouse.federation.entities_resolver_namespace`. -When you need to retrieve information from subgraphs, -the gateway automatically generates a request to the corresponding endpoint of the subgraph. +When you need to retrieve information from subgraphs, the gateway automatically generates a request to the corresponding endpoint of the subgraph. More details about this can be found in section [Query.\_entities of the Apollo Federation docs](https://www.apollographql.com/docs/federation/building-supergraphs/subgraphs-overview#query_entities). An example of such a request is shown below: @@ -25,10 +23,8 @@ An example of such a request is shown below: ## Single Entity Resolvers -After validating that type `Foo` exists, Lighthouse will look for a resolver class -in the namespace configured in `lighthouse.federation.entities_resolver_namespace`. -The resolver class is expected to contain a method `__invoke()` which takes -a single argument: the array form of the representation. +After validating that type `Foo` exists, Lighthouse will look for a resolver class in the namespace configured in `lighthouse.federation.entities_resolver_namespace`. +The resolver class is expected to contain a method `__invoke()` which takes a single argument: the array form of the representation. ```php namespace App\GraphQL\ReferenceResolvers; @@ -66,8 +62,7 @@ final class Foo ## Batched Entity Resolvers When the client requests a large number of entities with the same type, it can be more efficient to resolve them all at once. -When your entity resolver class implements `Nuwave\Lighthouse\Federation\BatchedEntityResolver`, -Lighthouse will call it a single time with an array of all representations of its type. +When your entity resolver class implements `Nuwave\Lighthouse\Federation\BatchedEntityResolver`, Lighthouse will call it a single time with an array of all representations of its type. The resolver can then do some kind of batch query to resolve them and return them all at once. ```php @@ -87,8 +82,7 @@ final class Foo implements BatchedEntityResolver } ``` -The returned iterable _must_ have the same keys as the given `array $representations` -to enable Lighthouse to return the results in the correct order. +The returned iterable _must_ have the same keys as the given `array $representations` to enable Lighthouse to return the results in the correct order. ```php namespace App\GraphQL\ReferenceResolvers; @@ -118,8 +112,7 @@ final class Product implements BatchedEntityResolver ## Eloquent Model Resolvers -When no resolver class can be found, Lighthouse will attempt to find the model that -matches the type `__typename`, using the namespaces configured in `lighthouse.namespaces.models`. +When no resolver class can be found, Lighthouse will attempt to find the model that matches the type `__typename`, using the namespaces configured in `lighthouse.namespaces.models`. ```graphql { @@ -131,8 +124,7 @@ matches the type `__typename`, using the namespaces configured in `lighthouse.na } ``` -The additional fields in the representation constrain the query builder, which is then -called and expected to return a single result. +The additional fields in the representation constrain the query builder, which is then called and expected to return a single result. In simplified terms, Lighthouse will do this: ```php @@ -149,5 +141,4 @@ return $results->first(); ``` The default model resolver makes one database query for each entity. -Therefore, for a large number of entities, it is worth considering [Batched Entity Resolvers](reference-resolvers.md#batched-entity-resolvers) -to avoid this issue. +Therefore, for a large number of entities, it is worth considering [Batched Entity Resolvers](reference-resolvers.md#batched-entity-resolvers) to avoid this issue. diff --git a/docs/6/getting-started/configuration.md b/docs/6/getting-started/configuration.md index ff948a5cac..f3bbabd076 100644 --- a/docs/6/getting-started/configuration.md +++ b/docs/6/getting-started/configuration.md @@ -11,9 +11,8 @@ The configuration file will be placed in `config/lighthouse.php`. ## CORS -A GraphQL API can be consumed from multiple clients, which may or may not reside -on the same domain as your server. Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) -for your GraphQL endpoint in `config/cors.php`: +A GraphQL API can be consumed from multiple clients, which may or may not reside on the same domain as your server. +Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) for your GraphQL endpoint in `config/cors.php`: ```diff return [ diff --git a/docs/6/getting-started/installation.md b/docs/6/getting-started/installation.md index 1c36ca6c41..baf0c0c2e1 100644 --- a/docs/6/getting-started/installation.md +++ b/docs/6/getting-started/installation.md @@ -10,8 +10,8 @@ composer require nuwave/lighthouse ## Publish the default schema -Lighthouse includes a default schema to get you going right away. Publish -it using the following `artisan` command: +Lighthouse includes a default schema to get you going right away. +Publish it using the following `artisan` command: ```shell php artisan vendor:publish --tag=lighthouse-schema @@ -39,9 +39,8 @@ $app->register(\Nuwave\Lighthouse\LighthouseServiceProvider::class); ``` The many features Lighthouse provides are split across multiple service providers. -Since Lumen does not support auto-discovery, you will have to register them individually -depending on which features you want to use. Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), -the section `extra.laravel.providers` contains the default service providers. +Since Lumen does not support auto-discovery, you will have to register them individually depending on which features you want to use. +Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), the section `extra.laravel.providers` contains the default service providers. To get you going right away in Lumen, copy over the included default schema. It uses pagination and validation, so you need to register the service providers. @@ -69,8 +68,7 @@ For Phpstorm, we recommend [the GraphQL plugin](https://plugins.jetbrains.com/pl ## Install GraphQL DevTools -To make use of the amazing tooling around GraphQL, we recommend -installing [GraphiQL](https://github.com/mll-lab/laravel-graphiql). +To make use of the amazing tooling around GraphQL, we recommend installing [GraphiQL](https://github.com/mll-lab/laravel-graphiql). ```shell composer require mll-lab/laravel-graphiql @@ -78,5 +76,5 @@ composer require mll-lab/laravel-graphiql After installation, visit `/graphiql` to try it. -You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in -the config. By default, the endpoint lives at `/graphql`. +You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in the config. +By default, the endpoint lives at `/graphql`. diff --git a/docs/6/getting-started/migrating-to-lighthouse.md b/docs/6/getting-started/migrating-to-lighthouse.md index f1e0514e0d..531660db6a 100644 --- a/docs/6/getting-started/migrating-to-lighthouse.md +++ b/docs/6/getting-started/migrating-to-lighthouse.md @@ -1,15 +1,12 @@ # Migrating to Lighthouse -This section contains advice on how you can migrate existing -API projects to Lighthouse. +This section contains advice on how you can migrate existing API projects to Lighthouse. ## Schema definition -The most important thing to get you started using Lighthouse will -be a schema that is written using GraphQL Schema Definition Language. +The most important thing to get you started using Lighthouse will be a schema that is written using GraphQL Schema Definition Language. -If you already have a server with another library up and running, you -can use introspection to retrieve this schema and save it to a file. +If you already have a server with another library up and running, you can use introspection to retrieve this schema and save it to a file. A simple tool that is also generally useful is [graphql-cli](https://github.com/graphql-cli/graphql-cli). @@ -17,23 +14,18 @@ A simple tool that is also generally useful is [graphql-cli](https://github.com/ graphql init graphql get-schema --endpoint=example.com/graphql --output=schema.graphql -Type definitions that previously done through code can mostly be deduced from -the schema. Sometimes, additional annotations or a PHP implementation is required. +Type definitions that previously done through code can mostly be deduced from the schema. +Sometimes, additional annotations or a PHP implementation is required. [How to define types](../the-basics/types.md) ## Resolver logic -If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), -[rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that -is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), -you should be able to reuse much of your existing code. +If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), [rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), you should be able to reuse much of your existing code. -You can also register your existing types within Lighthouse's type registry, so you -won't have to rewrite them in SDL: [Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). +You can also register your existing types within Lighthouse's type registry, so you won't have to rewrite them in SDL. +[Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). -Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature), -so you should be able to reuse any logic you have written for Queries/Mutations. +Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature). +You should be able to reuse any logic you have written for Queries/Mutations. -Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), -[eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), -[pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). +Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), [eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), [pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). diff --git a/docs/6/performance/caching.md b/docs/6/performance/caching.md index 20a7656707..d0e4cda179 100644 --- a/docs/6/performance/caching.md +++ b/docs/6/performance/caching.md @@ -1,8 +1,7 @@ # Caching -If some fields in your schema are expensive or slow to compute, it can be -beneficial to cache their result. Use the [@cache](../api-reference/directives.md#cache) -directive to instruct Lighthouse to cache the result of a resolver. +If some fields in your schema are expensive or slow to compute, it can be beneficial to cache their result. +Use the [@cache](../api-reference/directives.md#cache) directive to instruct Lighthouse to cache the result of a resolver. The cache is created on the first request and is cached forever by default. Use this for values that seldom change and take long to fetch/compute. @@ -32,8 +31,7 @@ type Query { ## Clear cache -To enable this feature, you need to use a cache store that supports [cache tags](https://laravel.com/docs/cache#cache-tags) -and enable cache tags in `config/lighthouse.php`: +To enable this feature, you need to use a cache store that supports [cache tags](https://laravel.com/docs/cache#cache-tags) and enable cache tags in `config/lighthouse.php`: ```php /* @@ -47,9 +45,9 @@ and enable cache tags in `config/lighthouse.php`: 'cache_directive_tags' => true, ``` -Now, you can place the [@clearCache](../api-reference/directives.md#clearcache) directive on -mutation fields. When they are queried, they will invalidate all cache entries associated with -a calculated tag. Depending on the effect of the mutation, you can clear different tags. +Now, you can place the [@clearCache](../api-reference/directives.md#clearcache) directive on mutation fields. +When they are queried, they will invalidate all cache entries associated with a calculated tag. +Depending on the effect of the mutation, you can clear different tags. Update the cache associated with a given type without a specific ID: @@ -93,8 +91,7 @@ If your mutation affects multiple levels of cache, you can apply this directive ## Cache key When generating a cached result for a resolver, Lighthouse produces a unique key for each type. -By default, Lighthouse will look for a field of type `ID` on the parent to generate the key -for a field with [@cache](../api-reference/directives.md#cache). +By default, Lighthouse will look for a field of type `ID` on the parent to generate the key for a field with [@cache](../api-reference/directives.md#cache). This directive allows to use a different field (i.e., an external API id): @@ -107,26 +104,21 @@ type GithubProfile { ## Implementing your own cache key generator -In one of your application service providers, bind the [`Nuwave\Lighthouse\Cache\CacheKeyAndTags.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTags.php) -interface to your cache key generator class: +In one of your application service providers, bind the [`Nuwave\Lighthouse\Cache\CacheKeyAndTags.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTags.php) interface to your cache key generator class: ```php $this->app->bind(CacheKeyAndTags::class, YourOwnCacheKeyGenerator::class); ``` -You can extend [`Nuwave\Lighthouse\Cache\CacheKeyAndTagsGenerator.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTagsGenerator.php) -to override certain methods, or implement the interface from scratch. +You can extend [`Nuwave\Lighthouse\Cache\CacheKeyAndTagsGenerator.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTagsGenerator.php) to override certain methods, or implement the interface from scratch. ## HTTP Cache-Control header **Experimental: not enabled by default, not guaranteed to be stable.** -Register the service provider `Nuwave\Lighthouse\CacheControl\CacheControlServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\CacheControl\CacheControlServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). -You can change the [`Cache-Control` header](https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control) of your response -regardless of [@cache](../api-reference/directives.md#cache) -by adding the [@cacheControl](../api-reference/directives.md#cachecontrol) directive to a field. +You can change the [`Cache-Control` header](https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control) of your response regardless of [@cache](../api-reference/directives.md#cache) by adding the [@cacheControl](../api-reference/directives.md#cachecontrol) directive to a field. The directive can be defined on the field-level or type-level. Note that field-level settings override type-level settings. diff --git a/docs/6/performance/deferred.md b/docs/6/performance/deferred.md index 2c5aa037d4..ca7bb7726f 100644 --- a/docs/6/performance/deferred.md +++ b/docs/6/performance/deferred.md @@ -2,22 +2,19 @@ **Experimental: not enabled by default, not guaranteed to be stable.** -Deferring fields allows you to prioritize fetching data needed to render the most important content -as fast as possible, and then loading the rest of the page in the background. +Deferring fields allows you to prioritize fetching data needed to render the most important content as fast as possible. +Then loading the rest of the page in the background. Lighthouse adds support for [the `@defer` directive](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md) through an extension. ## Setup -Register the service provider `Nuwave\Lighthouse\Defer\DeferServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Defer\DeferServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## Configuration -Consider the configuration options under `defer` in your `config/lighthouse.php` -to prevent deferred queries from running to long. +Consider the configuration options under `defer` in your `config/lighthouse.php` to prevent deferred queries from running to long.
-![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) -_(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ +![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) _(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ diff --git a/docs/6/performance/n-plus-one.md b/docs/6/performance/n-plus-one.md index 141dc23971..b84307fa7e 100644 --- a/docs/6/performance/n-plus-one.md +++ b/docs/6/performance/n-plus-one.md @@ -1,10 +1,8 @@ # The N+1 Query Problem -A common performance pitfall that comes with the nested nature of GraphQL queries -is the so-called N+1 query problem. +A common performance pitfall that comes with the nested nature of GraphQL queries is the so-called N+1 query problem. -Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the -name of the associated author: +Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the name of the associated author: ```graphql { @@ -17,19 +15,14 @@ name of the associated author: } ``` -Following a naive execution strategy, Lighthouse would first query a list of posts, -then loop over that list and resolve the individual fields. -The associated author for each post would be lazily loaded, querying the database -once per post. +Following a naive execution strategy, Lighthouse would first query a list of posts, then loop over that list and resolve the individual fields. +The associated author for each post would be lazily loaded, querying the database once per post. ## Eager Loading Relationships -When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) -is commonly used to alleviate the N+1 query problem. +When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) is commonly used to alleviate the N+1 query problem. -You can leverage eager loading by informing Lighthouse of the relationships between your models, -using directives such as [@belongsTo](../api-reference/directives.md#belongsto), [@hasMany](../api-reference/directives.md#hasmany) -and [@with](../api-reference/directives.md#with). +You can leverage eager loading by informing Lighthouse of the relationships between your models, using directives such as [@belongsTo](../api-reference/directives.md#belongsto), [@hasMany](../api-reference/directives.md#hasmany) and [@with](../api-reference/directives.md#with). ```graphql type Post { @@ -45,13 +38,12 @@ type User { Under the hood, Lighthouse will batch the relationship queries together in a single database query. -If you require a relation to be loaded for some field, but do not wish to return the relationship itself, -you can use the [@with](../api-reference/directives.md#with) directive. +If you require a relation to be loaded for some field. +Do not wish to return the relationship itself, you can use the [@with](../api-reference/directives.md#with) directive. ## Custom Batch Loaders -In the following example, the `User` model is associated with multiple posts, but the posts -are part of an external service. +In the following example, the `User` model is associated with multiple posts, but the posts are part of an external service. ```graphql type User { @@ -76,12 +68,11 @@ Since we have multiple users, `User.posts` would be resolved multiple times in t } ``` -We want to have a batch loader for `User.posts`, since it loads posts from a third party and the -call to fetch them is slow when run sequentially. This is assuming the posts service offers a method -to query posts for multiple users in one call. +We want to have a batch loader for `User.posts`, since it loads posts from a third party and the call to fetch them is slow when run sequentially. +This is assuming the posts service offers a method to query posts for multiple users in one call. -In order for Lighthouse to perform batch loading, it needs to group fields that are on the same level -in the query tree, but nested under different indices. When looking at the query path from `posts`, they may look like: +In order for Lighthouse to perform batch loading, it needs to group fields that are on the same level in the query tree, but nested under different indices. +When looking at the query path from `posts`, they may look like: - `users.0.posts` - `users.1.posts` @@ -107,8 +98,7 @@ function (User $user, array $args, GraphQLContext $context, ResolveInfo $resolve } ``` -The implementation of `UserPostsBatchLoader` is up to you, the only important thing is that the resolver -returns an instance of `GraphQL\Deferred`, see [webonyx/graphql-php docs](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). +The implementation of `UserPostsBatchLoader` is up to you, the only important thing is that the resolver returns an instance of `GraphQL\Deferred`, see [webonyx/graphql-php docs](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). The following example illustrates some common patterns that may be found in a batch loader implementation: ```php diff --git a/docs/6/performance/query-caching.md b/docs/6/performance/query-caching.md index e3efc12ab9..d79910cafb 100644 --- a/docs/6/performance/query-caching.md +++ b/docs/6/performance/query-caching.md @@ -59,8 +59,7 @@ Other reasons to clear the query cache completely include: ## Automated Persisted Queries -Lighthouse supports Automatic Persisted Queries (APQ), compatible with the -[Apollo implementation](https://www.apollographql.com/docs/apollo-server/performance/apq). +Lighthouse supports Automatic Persisted Queries (APQ), compatible with the [Apollo implementation](https://www.apollographql.com/docs/apollo-server/performance/apq). APQ is enabled by default, but depends on query caching being enabled. diff --git a/docs/6/performance/schema-caching.md b/docs/6/performance/schema-caching.md index 41259174bf..4e8ac8eb2b 100644 --- a/docs/6/performance/schema-caching.md +++ b/docs/6/performance/schema-caching.md @@ -1,22 +1,20 @@ # Schema caching -As your schema grows larger, the construction of the schema from raw `.graphql` files -becomes more and more costly. +As your schema grows larger, the construction of the schema from raw `.graphql` files becomes more and more costly. Schema caching is enabled in non-local environments by default, see `config/lighthouse.php`. ## Deployment -Update your cache when deploying a new version of your application -using the [cache](../api-reference/commands.md#cache) artisan command: +Update your cache when deploying a new version of your application using the [cache](../api-reference/commands.md#cache) artisan command: ```shell php artisan lighthouse:cache ``` The structure of the serialized schema can change between Lighthouse releases. -In order to prevent errors, use a deployment method that atomically updates -both the cache file and the dependencies, e.g. K8s. +In order to prevent errors, use a deployment method that atomically updates both the cache file and the dependencies, e.g. +K8s. ## Development diff --git a/docs/6/performance/server-configuration.md b/docs/6/performance/server-configuration.md index 9339ebf235..561c14b335 100644 --- a/docs/6/performance/server-configuration.md +++ b/docs/6/performance/server-configuration.md @@ -9,5 +9,4 @@ If you have the freedom to install it on your server, it's an easy way to get a ## Xdebug -Enabling Xdebug and having an active debug session slows down execution by -an order of magnitude. +Enabling Xdebug and having an active debug session slows down execution by an order of magnitude. diff --git a/docs/6/performance/tracing.md b/docs/6/performance/tracing.md index 49a431d9f8..5c9a3736ae 100644 --- a/docs/6/performance/tracing.md +++ b/docs/6/performance/tracing.md @@ -4,8 +4,7 @@ Tracing offers field-level performance monitoring for your GraphQL server. ## Setup -Register the service provider `Nuwave\Lighthouse\Tracing\TracingServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Tracing\TracingServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## Drivers diff --git a/docs/6/security/authentication.md b/docs/6/security/authentication.md index 8dcee6bcc2..5009fdb65c 100644 --- a/docs/6/security/authentication.md +++ b/docs/6/security/authentication.md @@ -1,16 +1,13 @@ # Authentication -You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) -to authenticate users of your GraphQL API. +You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) to authenticate users of your GraphQL API. ## AttemptAuthentication middleware -As all GraphQL requests are served at a single HTTP endpoint, middleware added -through the `lighthouse.php` config will run for all queries against your server. +As all GraphQL requests are served at a single HTTP endpoint, middleware added through the `lighthouse.php` config will run for all queries against your server. -In most cases, your schema will have some publicly accessible fields and others -that require authentication. As multiple checks for authentication or permissions may be -required in a single request, it is convenient to attempt authentication once per request. +In most cases, your schema will have some publicly accessible fields and others that require authentication. +As multiple checks for authentication or permissions may be required in a single request, it is convenient to attempt authentication once per request. ```php 'route' => [ @@ -20,12 +17,11 @@ required in a single request, it is convenient to attempt authentication once pe ], ``` -Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated -access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. +Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. -If you want to guard all your fields against unauthenticated access, you can simply add -Laravel's build-in auth middleware. Beware that this approach does not allow any GraphQL -operations for guest users, so you will have to handle login outside GraphQL. +If you want to guard all your fields against unauthenticated access, you can simply add Laravel's built-in auth middleware. +Beware that this approach does not allow any GraphQL operations for guest users. +So you will have to handle login outside GraphQL. ```php 'middleware' => [ @@ -41,16 +37,15 @@ You can configure default guards to use for authenticating GraphQL requests in ` 'guards' => ['api'], ``` -This setting is used whenever Lighthouse looks for an authenticated user, for example in directives -such as [@guard](../api-reference/directives.md#guard), or when applying the `AttemptAuthentication` middleware. +This setting is used whenever Lighthouse looks for an authenticated user, for example in directives such as [@guard](../api-reference/directives.md#guard). +Or when applying the `AttemptAuthentication` middleware. When multiple guards are configured, the first one that is authenticated will be used. Stateless guards are recommended for most use cases, such as the default `api` guard. ### Laravel Sanctum -If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard -to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the first middleware for Lighthouse's route. +If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the first middleware for Lighthouse's route. ```php 'route' => [ @@ -64,11 +59,9 @@ to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the f 'guards' => ['sanctum'], ``` -Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) -with all GraphQL requests, regardless of whether the user is authenticated or not. +Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) with all GraphQL requests, regardless of whether the user is authenticated or not. -When using [mll-lab/laravel-graphiql](https://github.com/mll-lab/laravel-graphiql), follow the [instructions -to add a CSRF token](https://github.com/mll-lab/laravel-graphiql#configure-session-authentication). +When using [mll-lab/laravel-graphiql](https://github.com/mll-lab/laravel-graphiql), follow the [instructions to add a CSRF token](https://github.com/mll-lab/laravel-graphiql#configure-session-authentication). ## Guard selected fields @@ -80,8 +73,8 @@ type Query { } ``` -If you need to guard multiple fields, use [@guard](../api-reference/directives.md#guard) -on a `type` or an `extend type` definition. It will be applied to all fields within that type. +If you need to guard multiple fields, use [@guard](../api-reference/directives.md#guard) on a `type` or an `extend type` definition. +It will be applied to all fields within that type. ```graphql extend type Query @guard { @@ -90,8 +83,7 @@ extend type Query @guard { } ``` -The `@guard` directive will be prepended to other directives defined on the fields -and thus executes before them. +The `@guard` directive will be prepended to other directives defined on the fields and thus executes before them. ```graphql extend type Query { @@ -113,8 +105,8 @@ type Query { } ``` -Sending the following query will return the authenticated user's info -or `null` if the request is not authenticated. +Sending the following query returns the authenticated user info. +It returns `null` if the request is not authenticated. ```graphql { @@ -127,9 +119,7 @@ or `null` if the request is not authenticated. ## Stateful Authentication Example -You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). -**This only works when Lighthouse's guard uses a session driver.** -Laravel's token based authentication does not allow logging in or out on the server side. +You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). **This only works when Lighthouse's guard uses a session driver.** Laravel's token based authentication does not allow logging in or out on the server side. The implementation in the docs is only an example and may have to be adapted to your specific use case. diff --git a/docs/6/security/authorization.md b/docs/6/security/authorization.md index c9625101e7..de84df9814 100644 --- a/docs/6/security/authorization.md +++ b/docs/6/security/authorization.md @@ -3,8 +3,7 @@ Not every user in your application may be allowed to see all data or do any action. You can control what they can do by enforcing authorization rules. -Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's -a prerequisite to have your users logged in before checking what they can do. +Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's a prerequisite to have your users logged in before checking what they can do. ## Use the Viewer pattern @@ -56,8 +55,7 @@ Now, authenticated users can query for items that belong to them and are natural ## Restrict fields through policies Lighthouse allows you to restrict field operations to a certain group of users. -Use the [@can\* family of directives](../api-reference/directives.md#can-family-of-directives) -to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. +Use the [@can\* family of directives](../api-reference/directives.md#can-family-of-directives) to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. Starting from Laravel 5.7, [authorization of guest users](https://laravel.com/docs/authorization#guest-users) is supported. Because of this, Lighthouse does **not** validate that the user is authenticated before passing it along to the policy. @@ -87,8 +85,7 @@ final class PostPolicy ### Protect mutations using database queries -You can also protect specific models by using the [@canFind](../api-reference/directives.md#canfind) -or [@canQuery](../api-reference/directives.md#canquery) directive. +You can also protect specific models by using the [@canFind](../api-reference/directives.md#canfind) or [@canQuery](../api-reference/directives.md#canquery) directive. They will query the database and check the specified policy against the result. ```graphql @@ -186,8 +183,7 @@ final class PostPolicy } ``` -You can pass along the client given input data as arguments to the policy checks -with the `injectArgs` argument: +You can pass along the client given input data as arguments to the policy checks with the `injectArgs` argument: ```graphql type Mutation { @@ -207,8 +203,7 @@ final class PostPolicy } ``` -When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as -the second parameter and the static `args` as the third parameter: +When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as the second parameter and the static `args` as the third parameter: ```php final class PostPolicy @@ -240,15 +235,12 @@ The `banned` field would return false for all users who are not authorized to ac ## Custom field restrictions -For applications with role management, it is common to hide some model attributes from a -certain group of users. At the moment, Laravel and Lighthouse offer no canonical solution -for this. +For applications with role management, it is common to hide some model attributes from a certain group of users. +At the moment, Laravel and Lighthouse offer no canonical solution for this. -A great way to implement something that fits your use case is to create -[a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). +A great way to implement something that fits your use case is to create [a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). Field middleware allows you to intercept field access and conditionally hide them. -You can hide a field by returning `null` instead of calling the final resolver, or maybe even -abort execution by throwing an error. +You can hide a field by returning `null` instead of calling the final resolver, or maybe even abort execution by throwing an error. The following directive `@canAccess` is an example implementation, make sure to adapt it to your needs. It assumes a simple role system where a `User` has a single attribute `$role`. diff --git a/docs/6/security/sanitization.md b/docs/6/security/sanitization.md index 05560796b9..5c20de2141 100644 --- a/docs/6/security/sanitization.md +++ b/docs/6/security/sanitization.md @@ -1,16 +1,14 @@ # Sanitization When dealing with user input, you need to make sure the given data is valid. -While [validation](validation) is a great first line of defense, there are cases where -it is most practical to modify the given input to ensure it is valid or safe to use. +While [validation](validation) is a great first line of defense, there are cases where it is most practical to modify the given input to ensure it is valid or safe to use. ## Single arguments A great way to deal with single values is to use an [`ArgTransformerDirective`](../custom-directives/field-argument-directives#argtransformerdirective). Lighthouse offers a few built-in options, but it is also really easy to build your own. -Here is how you can remove whitespace of a given input string by using -the built-in [@trim](../api-reference/directives.md#trim) directive: +Here is how you can remove whitespace of a given input string by using the built-in [@trim](../api-reference/directives.md#trim) directive: ```graphql type Mutation { @@ -20,6 +18,4 @@ type Mutation { ## Complex arguments -When you need to look at multiple input fields in order to run sanitization, you can use -a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) -to transform the given inputs before passing them along to the final resolver. +When you need to look at multiple input fields in order to run sanitization, you can use a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) to transform the given inputs before passing them along to the final resolver. diff --git a/docs/6/security/validation.md b/docs/6/security/validation.md index e885b9cc8d..bbb293d5a9 100644 --- a/docs/6/security/validation.md +++ b/docs/6/security/validation.md @@ -1,12 +1,10 @@ # Validation -Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) -for your queries and mutations. +Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) for your queries and mutations. ## Single Arguments -The simplest way to leverage the built-in validation rules is to use the -[@rules](../api-reference/directives.md#rules) directive. +The simplest way to leverage the built-in validation rules is to use the [@rules](../api-reference/directives.md#rules) directive. ```graphql type Mutation { @@ -14,8 +12,8 @@ type Mutation { } ``` -In the case of a validation error, Lighthouse will abort execution and return the validation messages -as part of the response. +If validation fails, Lighthouse aborts execution. +It returns the validation messages as part of the response. ```graphql mutation { @@ -96,11 +94,10 @@ input CreatePostInput { } ``` -Using the [`unique`](https://laravel.com/docs/validation#rule-unique) -validation rule can be a bit tricky. +Using the [`unique`](https://laravel.com/docs/validation#rule-unique) validation rule can be a bit tricky. -If the argument is nested within an input object, the argument path will not -match the column name, so you have to specify the column name explicitly. +If the argument is nested within an input object, the argument path will not match the column name. +So you have to specify the column name explicitly. ```graphql input CreateUserInput { @@ -110,8 +107,7 @@ input CreateUserInput { ## Validating Arrays -When you are passing in an array as an argument to a field, you might -want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) +When you are passing in an array as an argument to a field, you might want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) ```graphql type Mutation { @@ -122,8 +118,7 @@ type Mutation { } ``` -You can also combine this with [@rules](../api-reference/directives.md#rules) to validate -both size and contents of an argument array. +You can also combine this with [@rules](../api-reference/directives.md#rules) to validate both size and contents of an argument array. For example, you might require a list of at least 3 valid emails to be passed. ```graphql @@ -136,9 +131,9 @@ type Mutation { ## Validator Classes -In cases where your validation becomes too complex and demanding, you want to have the power of PHP to perform -complex validation. For example, accessing existing data in the database or validating the combination of input -values cannot be achieved with the examples above. This is where validator classes come into play. +In cases where your validation becomes too complex and demanding, you want to have the power of PHP to perform complex validation. +For example, accessing existing data in the database or validating the combination of input values cannot be achieved with the examples above. +This is where validator classes come into play. Validator classes can be reused on field definitions or input types within your schema. Use the [@validator](../api-reference/directives.md#validator) directive: @@ -150,15 +145,15 @@ input UpdateUserInput @validator { } ``` -We need to back that with a validator class. Lighthouse uses a simple naming convention for validator classes, -use the name of the input type and append `Validator`: +We need to back that with a validator class. +Lighthouse uses a simple naming convention for validator classes, use the name of the input type and append `Validator`: ```shell php artisan lighthouse:validator UpdateUserInputValidator ``` -The resulting class will be placed in your configured validator namespace. Let's go ahead -and define the validation rules for the input: +The resulting class will be placed in your configured validator namespace. +Let's go ahead and define the validation rules for the input: ```php namespace App\GraphQL\Validators; @@ -183,8 +178,8 @@ final class UpdateUserInputValidator extends Validator } ``` -Note that this gives you access to all kinds of programmatic validation rules that Laravel -provides. This can give you additional flexibility when you need it. +Note that this gives you access to all kinds of programmatic validation rules that Laravel provides. +This can give you additional flexibility when you need it. ### Custom Validator Messages @@ -220,13 +215,13 @@ type Mutation { } ``` -In that case, Lighthouse will look for a validator class in a sub-namespace matching the parent type, in this case -that would be `Mutation`, so the default FQCN would be `App\GraphQL\Validators\Mutation\UpdateUserValidator`. +In that case, Lighthouse will look for a validator class in a sub-namespace matching the parent type, in this case that would be `Mutation`. +The default FQCN would be `App\GraphQL\Validators\Mutation\UpdateUserValidator`. ### Validator For Nested Inputs -Use multiple validators for complex inputs that include nested input objects. This ensures -they do not grow too complex and can be composed freely. +Use multiple validators for complex inputs that include nested input objects. +This ensures they do not grow too complex and can be composed freely. ## Caveats @@ -252,8 +247,8 @@ input FooInput { } ``` -The following mutation would pass validation, because `notBar` references the `bar` field of `FooInput` -and thus its value `1` is compared to the value `2` - which is different: +The following mutation would pass validation. +`notBar` references the `bar` field of `FooInput` and thus its value `1` is compared to the value `2`, which is different: ```graphql mutation { @@ -263,8 +258,8 @@ mutation { ### Custom Rules With References -When creating custom validation rules with references, you need to tell Lighthouse -which parameters are references, so it can add the full argument path: +When creating custom validation rules with references, you need to tell Lighthouse which parameters are references. +So it can add the full argument path: ```graphql input FooInput { @@ -273,8 +268,7 @@ input FooInput { } ``` -In this example, `equal_field` is a custom rule that checks if the argument -is the same as the one referenced by the parameter. +In this example, `equal_field` is a custom rule that checks if the argument is the same as the one referenced by the parameter. The parameters to `with_reference` are: @@ -288,8 +282,7 @@ Lighthouse will call this method with the argument path leading up to the valida ### Comparisons -If you need to validate the size of an integer, you need to add the -`integer` validation rule before: +If you need to validate the size of an integer, you need to add the `integer` validation rule before: ```graphql type Mutation { @@ -298,8 +291,7 @@ type Mutation { ``` Rules that reference other fields work strictly function as such. -For example, it is not possible to use `gt` to compare against a literal value, -use `min` instead: +For example, it is not possible to use `gt` to compare against a literal value, use `min` instead: ```graphql type Mutation { @@ -315,8 +307,7 @@ type Mutation { By default, Lighthouse enables all default query validation rules from `webonyx/graphql-php`. This covers fundamental checks, e.g. queried fields match the schema, variables have values of the correct type. -If you want to add custom rules or change which ones are used, you can bind a custom implementation -of the interface `Nuwave\Lighthouse\Support\Contracts\ProvidesCacheableValidationRules` through a service provider. +If you want to add custom rules or change which ones are used, you can bind a custom implementation of the interface `Nuwave\Lighthouse\Support\Contracts\ProvidesCacheableValidationRules` through a service provider. ```php use Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules; diff --git a/docs/6/subscriptions/client-implementations.md b/docs/6/subscriptions/client-implementations.md index ec615730fc..039e8f495e 100644 --- a/docs/6/subscriptions/client-implementations.md +++ b/docs/6/subscriptions/client-implementations.md @@ -1,12 +1,10 @@ # Client Implementations -To get you up and running quickly, the following sections show how to use subscriptions -with common GraphQL client libraries. +To get you up and running quickly, the following sections show how to use subscriptions with common GraphQL client libraries. ## Apollo for Pusher -To use Lighthouse Pusher subscriptions with the [Apollo](https://www.apollographql.com/docs/react) -client library you will need to create an `apollo-link`: +To use Lighthouse Pusher subscriptions with the [Apollo](https://www.apollographql.com/docs/react) client library you will need to create an `apollo-link`: ```js import { ApolloLink, Observable } from "apollo-link"; @@ -134,8 +132,7 @@ const link = ApolloLink.from([pusherLink, httpLink(`${API_LOCATION}/graphql`)]); ## Relay Modern -To use Lighthouse's Pusher subscriptions with Relay Modern you will -need to create a custom handler and inject it into Relay's environment. +To use Lighthouse's Pusher subscriptions with Relay Modern you will need to create a custom handler and inject it into Relay's environment. ```js import Pusher from "pusher-js"; @@ -240,8 +237,7 @@ export const environment = new Environment({ ## Flutter/Dart -To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will -need to create a custom link below: +To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will need to create a custom link below: ````dart import 'dart:async'; diff --git a/docs/6/subscriptions/defining-fields.md b/docs/6/subscriptions/defining-fields.md index c6ee24860a..ff15fe6ae8 100644 --- a/docs/6/subscriptions/defining-fields.md +++ b/docs/6/subscriptions/defining-fields.md @@ -17,8 +17,7 @@ php artisan lighthouse:subscription PostUpdated Lighthouse will look for a class matching the capitalized name of the field within the default subscription namespace. For example, the field `postUpdated` should have a corresponding class at `App\GraphQL\Subscriptions\PostUpdated`. -All subscription field classes **must** implement the abstract class `Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` -and implement the two methods `authorize` and `filter`. +All subscription field classes **must** implement the abstract class `Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` and implement the two methods `authorize` and `filter`. ```php namespace App\GraphQL\Subscriptions; @@ -85,6 +84,4 @@ final class PostUpdated extends GraphQLSubscription } ``` -If the default namespaces are not working with your application structure -or you want to be more explicit, you can use the [@subscription](../api-reference/directives.md#subscription) -directive to point to a different class. +If the default namespaces are not working with your application structure or you want to be more explicit, you can use the [@subscription](../api-reference/directives.md#subscription) directive to point to a different class. diff --git a/docs/6/subscriptions/filtering-subscriptions.md b/docs/6/subscriptions/filtering-subscriptions.md index c4101ac0c6..3c6d132093 100644 --- a/docs/6/subscriptions/filtering-subscriptions.md +++ b/docs/6/subscriptions/filtering-subscriptions.md @@ -1,6 +1,8 @@ # Filtering Subscriptions -There are times when you'll need to filter out specific events based on the arguments provided by the client. To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. For instance, using the following example: +There are times when you'll need to filter out specific events based on the arguments provided by the client. +To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. +For instance, using the following example: ```graphql subscription onPostUpdated($post_id: ID!) { diff --git a/docs/6/subscriptions/getting-started.md b/docs/6/subscriptions/getting-started.md index 21d20fcbd6..4e26b0f3d3 100644 --- a/docs/6/subscriptions/getting-started.md +++ b/docs/6/subscriptions/getting-started.md @@ -1,27 +1,20 @@ # Subscriptions: Getting Started -Subscriptions allow GraphQL clients to observe specific events -and receive updates from the server when those events occur. +Subscriptions allow GraphQL clients to observe specific events and receive updates from the server when those events occur. -::: tip NOTE -Much of the credit should be given to the [Ruby implementation](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/overview.md) as they provided a great overview of how the backend should work. -::: +::: tip NOTE Much of the credit should be given to the [Ruby implementation](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/overview.md) as they provided a great overview of how the backend should work. ::: ## Setup -Register the service provider `Nuwave\Lighthouse\Subscriptions\SubscriptionServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Subscriptions\SubscriptionServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). -If you want to use [the Pusher driver](https://laravel.com/docs/11.x/broadcasting#pusher-channels), you need to install the [Pusher PHP Library](https://github.com/pusher/pusher-http-php) -for interacting with the Pusher HTTP API. +If you want to use [the Pusher driver](https://laravel.com/docs/11.x/broadcasting#pusher-channels), you need to install the [Pusher PHP Library](https://github.com/pusher/pusher-http-php) for interacting with the Pusher HTTP API. composer require pusher/pusher-php-server -If you want to use [the Laravel Echo driver](https://laravel.com/docs/broadcasting#client-side-installation), -you need to set the env `LIGHTHOUSE_BROADCASTER=echo`. +If you want to use [the Laravel Echo driver](https://laravel.com/docs/broadcasting#client-side-installation), you need to set the env `LIGHTHOUSE_BROADCASTER=echo`. -When using subscriptions with [Laravel Octane](https://laravel.com/docs/octane), -add the following to your `config/octane.php`: +When using subscriptions with [Laravel Octane](https://laravel.com/docs/octane), add the following to your `config/octane.php`: ```php 'warm' => [ @@ -33,17 +26,17 @@ add the following to your `config/octane.php`: ### Empty Response Optimization Lighthouse returns the subscription channel as part of the response under `extensions`. -If `subscriptions.exclude_empty` in `lighthouse.php` is set to `true`, -API responses without a subscription channel will not contain `lighthouse_subscriptions` in `extensions`. -This optimizes performance by sending less data, but clients must anticipate this appropriately. +If `subscriptions.exclude_empty` in `lighthouse.php` is set to `true`, API responses without a subscription channel will not contain `lighthouse_subscriptions` in `extensions`. +This optimizes performance by sending less data, +but clients must anticipate this appropriately. ## Expiring Subscriptions Subscriptions do not expire by themselves. Unless you delete a subscription, it will continue to broadcast events after the client has disconnected. -The easiest way to expire subscriptions automatically is to use the env `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL` -to set an expiration time in seconds (e.g. `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL=3600` to expire in one hour). +The easiest way to expire subscriptions automatically is to use the env `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL` to set an expiration time in seconds (e.g. +`LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL=3600` to expire in one hour). ## Encrypted Subscriptions @@ -76,4 +69,5 @@ The webhook URL will typically be: /graphql/subscriptions/webhook ``` -You can add the webhook in the Pusher Dashboard. Select the type `channel existence`. +You can add the webhook in the Pusher Dashboard. +Select the type `channel existence`. diff --git a/docs/6/subscriptions/trigger-subscriptions.md b/docs/6/subscriptions/trigger-subscriptions.md index 8c283056b2..33307b4422 100644 --- a/docs/6/subscriptions/trigger-subscriptions.md +++ b/docs/6/subscriptions/trigger-subscriptions.md @@ -1,12 +1,10 @@ # Trigger Subscriptions -Now that clients can subscribe to a field, you will need to notify Lighthouse -when the underlying data has changed. +Now that clients can subscribe to a field, you will need to notify Lighthouse when the underlying data has changed. ## Broadcast Directive -The [@broadcast](../api-reference/directives.md#broadcast) -directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. +The [@broadcast](../api-reference/directives.md#broadcast) directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. ```graphql type Mutation { @@ -15,13 +13,11 @@ type Mutation { } ``` -You can reference the same subscription from multiple fields, or vice-versa -trigger multiple subscriptions from a single field. +You can reference the same subscription from multiple fields, or vice-versa trigger multiple subscriptions from a single field. ## Fire Subscriptions From Code -The `Subscription` class offers a utility method `broadcast` -that can be used to broadcast subscriptions from anywhere in your application. +The `Subscription` class offers a utility method `broadcast` that can be used to broadcast subscriptions from anywhere in your application. It accepts three parameters: @@ -29,8 +25,7 @@ It accepts three parameters: - `mixed $root` The result object you want to pass through - `bool $shouldQueue = null` Optional, overrides the default configuration `lighthouse.subscriptions.queue_broadcasts` -The following example shows how to trigger a subscription after an update -to the `Post` model. +The following example shows how to trigger a subscription after an update to the `Post` model. ```php $post->title = $newTitle; diff --git a/docs/6/testing/extensions.md b/docs/6/testing/extensions.md index e90a00ced7..326d257487 100644 --- a/docs/6/testing/extensions.md +++ b/docs/6/testing/extensions.md @@ -1,12 +1,10 @@ # Testing Lighthouse extensions -When you extend Lighthouse with custom functionality, it is a great idea to test -your extensions in isolation from the rest of your application. +When you extend Lighthouse with custom functionality, it is a great idea to test your extensions in isolation from the rest of your application. ## Use a test schema -When you enhance functionality related to the schema definition, such as adding -a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. +When you enhance functionality related to the schema definition, such as adding a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. Add the `UsesTestSchema` trait to your base test class, call `setUpTestSchema()` and define your test schema: ```php @@ -40,8 +38,8 @@ final class MyCustomDirectiveTest extends TestCase ## Mock resolvers -When testing custom functionality through a dummy schema, you still need to have -a way to resolve fields. Lighthouse provides a simple way to mock resolvers in a dummy schema. +When testing custom functionality through a dummy schema, you still need to have a way to resolve fields. +Lighthouse provides a simple way to mock resolvers in a dummy schema. Add the `MocksResolvers` trait to your test class: @@ -90,9 +88,9 @@ public function testReverseField(): void } ``` -Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert -that our resolver is called with certain values. Note that we are not passing an -explicit resolver function here. The default resolver will simply return `null`. +Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert that our resolver is called with certain values. +Note that we are not passing an explicit resolver function here. +The default resolver will simply return `null`. ```php public function testReverseInput(): void @@ -118,8 +116,7 @@ public function testReverseInput(): void } ``` -If you have to handle the incoming resolver arguments dynamically, you can also -pass a function that is called: +If you have to handle the incoming resolver arguments dynamically, you can also pass a function that is called: ```php public function testReverseInput(): void @@ -146,8 +143,8 @@ public function testReverseInput(): void } ``` -You might have a need to add multiple resolvers to a single schema. For that case, -specify a unique `key` for the mock resolver (it defaults to `default`): +You might have a need to add multiple resolvers to a single schema. +For that case, specify a unique `key` for the mock resolver (it defaults to `default`): ```php public function testMultipleResolvers(): void diff --git a/docs/6/testing/phpunit.md b/docs/6/testing/phpunit.md index c2b92b1656..f000307606 100644 --- a/docs/6/testing/phpunit.md +++ b/docs/6/testing/phpunit.md @@ -104,11 +104,9 @@ public function testPostsSubscription(): void ## Assertions -Now that we know how to query our server in tests, we need to make sure the -returned results match our expectations. +Now that we know how to query our server in tests, we need to make sure the returned results match our expectations. -The returned `TestResponse` conveniently offers assertions that work quite -well with the JSON data returned by GraphQL. +The returned `TestResponse` conveniently offers assertions that work quite well with the JSON data returned by GraphQL. The `assertJson` method asserts that the response is a superset of the given JSON. @@ -253,12 +251,9 @@ $this ## Testing Errors -Depending on your debug and error handling configuration, Lighthouse catches most if -not all errors produced within queries and includes them within the result. +Depending on your debug and error handling configuration, Lighthouse catches most if not all errors produced within queries and includes them within the result. -One way to test for errors is to examine the `TestResponse`, either by looking -at the JSON response manually or by using the provided [assertion mixins](#testresponse-assertion-mixins) -such as `assertGraphQLErrorMessage()`: +One way to test for errors is to examine the `TestResponse`, either by looking at the JSON response manually or by using the provided [assertion mixins](#testresponse-assertion-mixins) such as `assertGraphQLErrorMessage()`: ```php $this @@ -315,8 +310,8 @@ $this->multipartGraphQL($operations, $map, $file); ## Introspection -If you create or manipulate parts of your schema programmatically, you might -want to test that. You can use introspection to query your final schema in tests. +If you create or manipulate parts of your schema programmatically, you might want to test that. +You can use introspection to query your final schema in tests. Lighthouse uses the introspection query from [`GraphQL\Type\Introspection::getIntrospectionQuery()`](https://github.com/webonyx/graphql-php/blob/master/src/Type/Introspection.php). @@ -382,8 +377,7 @@ $this->setUpDeferStream(); ## Lumen -Because the `TestResponse` class is not available in Lumen, you must use a different -test trait: +Because the `TestResponse` class is not available in Lumen, you must use a different test trait: ```diff ` -and including it in your schema. Lighthouse will look for Scalar types in a configurable -default namespace. +Define your own scalar types with `php artisan lighthouse:scalar `. +Then include them in your schema. +Lighthouse will look for Scalar types in a configurable default namespace. ```graphql scalar ZipCode @@ -85,8 +84,8 @@ type Query { } ``` -In this example, the underlying values are actually integers. When the models are retrieved from -the database, the mapping is applied and the integers are converted to the defined string keys. +In this example, the underlying values are actually integers. +When the models are retrieved from the database, the mapping is applied and the integers are converted to the defined string keys. ```php return [ @@ -131,8 +130,7 @@ The PHP internal value of the field `ADMIN` will be `string('ADMIN')`. ### Native PHP definition -If you want to reuse enum definitions from PHP, you can [construct a `PhpEnumType`](https://webonyx.github.io/graphql-php/type-definitions/enums/#construction-from-php-enum) -and [register it through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types): +If you want to reuse enum definitions from PHP, you can [construct a `PhpEnumType`](https://webonyx.github.io/graphql-php/type-definitions/enums/#construction-from-php-enum) and [register it through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types): ```php use GraphQL\Type\Definition\Deprecated; @@ -158,8 +156,7 @@ $typeRegistry->register(new PhpEnumType(Fruit::class)); ### bensampo/laravel-enum -If you are using [bensampo/laravel-enum](https://github.com/BenSampo/laravel-enum) -you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. +If you are using [bensampo/laravel-enum](https://github.com/BenSampo/laravel-enum) you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. ```php use BenSampo\Enum\Enum; @@ -254,8 +251,7 @@ enum Color { ## Input Input types can be used to describe complex objects for field arguments. -Beware that while they look similar to Object Types, they behave differently: -The fields of an Input Type are treated similar to arguments. +Beware that while they look similar to Object Types, they behave differently: The fields of an Input Type are treated similar to arguments. ```graphql input CreateUserInput { @@ -303,20 +299,21 @@ type User implements Named { } ``` -Interfaces need a way of determining which concrete Object Type is returned by a -particular query. Lighthouse provides a default type resolver that works by calling -`class_basename($value)` on the value returned by the resolver. +Interfaces need a way of determining which concrete Object Type is returned by a particular query. +Lighthouse provides a default type resolver. +It calls `class_basename()` on the resolved value. -You can also provide a custom type resolver. Run `php artisan lighthouse:interface ` to create -a custom interface class. It is automatically put in the default namespace where Lighthouse can discover it by itself. +You can also provide a custom type resolver. +Run `php artisan lighthouse:interface ` to create a custom interface class. +It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) ## Union A Union is an abstract type that simply enumerates other Object Types. -They are similar to interfaces in that they can return different types, but do not prescribe any common fields. +They are similar to interfaces in that they can return different types. +But do not prescribe any common fields. ```graphql union Person = User | Employee @@ -333,8 +330,7 @@ type Employee { ``` Just like Interfaces, you need a way to determine the concrete Object Type for a Union, based on the resolved value. -If the default type resolver does not work for you, define your own using `php artisan lighthouse:union `. +If the default type resolver does not work for you, define your own with `php artisan lighthouse:union `. It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) diff --git a/docs/INDEX.md b/docs/INDEX.md index 0b2fdf5cae..8874c8e95d 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -2,7 +2,7 @@ home: true title: Lighthouse - A framework for serving GraphQL from Laravel heroImage: /logo.svg -actionText: Get Started → +actionText: Get Started → actionLink: /latest/getting-started/installation features: - title: đŸ“œ SDL First diff --git a/docs/master/api-reference/commands.md b/docs/master/api-reference/commands.md index 165d3d9f08..fa06f98ca1 100644 --- a/docs/master/api-reference/commands.md +++ b/docs/master/api-reference/commands.md @@ -51,8 +51,7 @@ This will create the following files: - `programmatic-types.graphql`: Schema definitions for programmatically registered types, if you have any - `_lighthouse_ide_helper.php`: Class definitions for some magical PHP, such as the `TestResponse` mixin -A great way to keep up to date with your current version of Lighthouse -is to add this script to your `composer.json`: +A great way to keep up to date with your current version of Lighthouse is to add this script to your `composer.json`: ```json "scripts": { @@ -62,8 +61,7 @@ is to add this script to your `composer.json`: ], ``` -If the generated definitions conflict with those provided by your IDE, try `--omit-built-in` to avoid redefining -built-in directives such as `@deprecated`. +If the generated definitions conflict with those provided by your IDE, try `--omit-built-in` to avoid redefining built-in directives such as `@deprecated`. ## interface @@ -94,7 +92,8 @@ php artisan lighthouse:print-schema This can be quite useful, as the root `.graphql` files do not necessarily contain the whole schema. Schema imports, native PHP types and schema manipulation may influence the final schema. -Use the `-W` / `--write` option to output the schema to the default file storage (usually `storage/app`) as `lighthouse-schema.graphql`. +Use the `-W` / `--write` option to output the schema to default file storage (usually `storage/app`). +The output file is `lighthouse-schema.graphql`. You can output your schema in JSON format by using the `--json` flag. You can sort the final compiled schema by using the `--sort` flag. diff --git a/docs/master/api-reference/directives.md b/docs/master/api-reference/directives.md index 58d5760124..5a81b2031b 100644 --- a/docs/master/api-reference/directives.md +++ b/docs/master/api-reference/directives.md @@ -131,8 +131,9 @@ directive @all( ) on FIELD_DEFINITION ``` -This assumes your model has the same name as the type you are returning and is defined -in the default model namespace `App`. [You can change this configuration](../getting-started/configuration.md). +This assumes your model has the same name as the returned type. +It also assumes the model is in the default namespace `App`. +[You can change this configuration](../getting-started/configuration.md). ```graphql type Query { @@ -194,8 +195,7 @@ type Query { } ``` -If you need to use a guard besides the default to resolve the authenticated user, -you can pass the guard name as the `guards` argument. +If you need to use a guard besides the default to resolve the authenticated user, you can pass the guard name as the `guards` argument. ```graphql type Query { @@ -256,8 +256,8 @@ final class Post extends Model } ``` -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument. +Use it when your relationship method name differs from the field name. ```graphql type Post { @@ -320,7 +320,8 @@ enum BelongsToManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -356,8 +357,8 @@ final class User extends Model ### Rename Relation -The directive accepts an optional `relation` argument if your relationship method -has a different name than the field. +The directive accepts an optional `relation` argument. +Use it when your relationship method name differs from the field name. ```graphql type User { @@ -371,12 +372,10 @@ You may want to allow accessing data that describes the relation between the mod See [retrieving intermediate table columns in Laravel](https://laravel.com/docs/eloquent-relationships#retrieving-intermediate-table-columns). Just like in Laravel, you can access the `pivot` attribute on the models (or its alias). -Even though this attribute is always present when querying the model through the relation, -it may not be present when reaching the node through another path in the schema, so it is -recommended to define the field as nullable (no `!`). +Even though this attribute is always present when querying the model through the relation, it may not be present when reaching the node through another path in the schema. +It is recommended to define the field as nullable (no `!`). -The following example assumes the intermediate table between `User` and `Role` defines -a column `meta`. +The following example assumes the intermediate table between `User` and `Role` defines a column `meta`. ```php use Illuminate\Database\Eloquent\Model; @@ -419,8 +418,7 @@ type RoleUserPivot { } ``` -When using the `type` argument with pagination style `CONNECTION`, you may create your own [edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) -that either contains the attributes of the intermediate table or contains a `pivot` field with the corresponding type. +When using the `type` argument with pagination style `CONNECTION`, you may create your own [edge type](https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types) that either contains the attributes of the intermediate table or contains a `pivot` field with the corresponding type. The custom edge type must contain at least the following two fields: @@ -569,8 +567,7 @@ final class CompanyBinding ### Binding a collection of instances -When the `@bind` directive is defined on an argument or input field with an array value, -it can be used to resolve a collection of instances. +When the `@bind` directive is defined on an argument or input field with an array value, it can be used to resolve a collection of instances. ```graphql type Mutation { @@ -642,8 +639,7 @@ type Mutation { } ``` -You may override the default queueing behavior from the configuration by -passing the `shouldQueue` argument. +You may override the default queueing behavior from the configuration by passing the `shouldQueue` argument. ```graphql type Mutation { @@ -679,16 +675,17 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar BuilderValue ``` -You must point to a `method` which will receive the builder instance -and can apply additional constraints to the query. +You must point to a `method` that receives the builder instance. +That method can apply additional constraints to the query. -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). -When used on an argument, the method is only called when the argument is specified (may be `null`), -and its value is passed as the second parameter. -When used on a field, the method is always called, and if the `value` argument is defined, -it is passed as the second parameter. +When used on an argument, the method is only called when the argument is specified (may be `null`). +And its value is passed as the second parameter. +When used on a field, the method is always called. +And if the `value` argument is defined, it is passed as the second parameter. ```graphql type Query { @@ -798,11 +795,13 @@ You can find usage examples of this directive in [the caching docs](../performan ## @can -Deprecated. Use the [@can\* family of directives](#can-family-of-directives) instead. +Deprecated. +Use the [@can\* family of directives](#can-family-of-directives) instead. ## @can\* family of directives -All `@can*` directives have common arguments. These arguments specify how gates are checked and what to do if the user is not authorized. +All `@can*` directives have common arguments. +These arguments specify how gates are checked and what to do if the user is not authorized. Each directive has its own set of arguments that specify what to check against. ```graphql @@ -1025,8 +1024,7 @@ type Query { } ``` -A custom complexity function may look like the following, -refer to the [complexity function signature](resolvers.md#complexity-function-signature). +A custom complexity function may look like the following, refer to the [complexity function signature](resolvers.md#complexity-function-signature). ```php namespace App\GraphQL\Security; @@ -1071,8 +1069,8 @@ type Mutation { } ``` -Non-nullable arguments will _not_ be converted when this directive is used on a field, -but will be converted when it is used directly on the argument. +Non-nullable arguments will _not_ be converted when this directive is used on a field. +But will be converted when it is used directly on the argument. ```graphql type Mutation { @@ -1083,8 +1081,7 @@ type Mutation { } ``` -If you want this for all your fields, consider adding this directive to your -global field middleware in `lighthouse.php`: +If you want this for all your fields, add this directive to your global field middleware in `lighthouse.php`: ```php 'field_middleware' => [ @@ -1177,8 +1174,7 @@ type Mutation { } ``` -If you are using a single input object as an argument, you must tell Lighthouse -to spread out the nested values before applying it to the resolver. +If you are using a single input object as an argument, you must tell Lighthouse to spread out the nested values before applying it to the resolver. ```graphql type Mutation { @@ -1190,8 +1186,8 @@ input CreatePostInput { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, set it with the `model` argument. +If the model is in a non-default namespace, also set it with the `model` argument. ```graphql type Mutation { @@ -1282,8 +1278,8 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, set it with the `model` argument. +If the model is in a non-default namespace, also set it with the `model` argument. ```graphql type Mutation { @@ -1300,9 +1296,7 @@ type Mutation { } ``` -If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or -`MorphTo` relationship, you can pass a Boolean instead of an ID, as there is only one -possible model that can be deleted. +If the model relates to a single other model through a `HasOne`, `MorphOne`, `BelongsTo` or `MorphTo` relationship, you can pass a Boolean instead of an ID, as there is only one possible model that can be deleted. ```graphql type Mutation { @@ -1337,8 +1331,8 @@ type Query { } ``` -Deprecated elements are not included in introspection queries by default, -but they can still be queried by clients. +Deprecated elements are not included in introspection queries by default. +But they can still be queried by clients. ## @drop @@ -1349,8 +1343,8 @@ Ignore the user given value, don't pass it to the resolver. directive @drop on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -This is useful when you want to deprecate a field, but avoid breaking changes -for clients that still pass the value. +This is useful when you want to deprecate a field. +But avoid breaking changes for clients that still pass the value. ```graphql type User { @@ -1397,9 +1391,7 @@ enum FeatureState { } ``` -Requires the installation of [Laravel Pennant](https://laravel.com/docs/pennant) -and manual registration of the service provider `Nuwave\Lighthouse\Pennant\PennantServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Requires the installation of [Laravel Pennant](https://laravel.com/docs/pennant) and manual registration of the service provider `Nuwave\Lighthouse\Pennant\PennantServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## @field @@ -1429,8 +1421,7 @@ type Mutation { } ``` -You can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md), -The following will look for a class in `App\GraphQL\Queries` by default. +You can take advantage of the default namespaces that are defined in the [configuration](../getting-started/configuration.md), The following will look for a class in `App\GraphQL\Queries` by default. ```graphql type Query { @@ -1438,8 +1429,8 @@ type Query { } ``` -Be aware that resolvers are not limited to root fields. A resolver can be used for basic tasks -such as transforming the value of scalar fields, e.g. reformat a date. +Be aware that resolvers are not limited to root fields. +A resolver can be used for basic tasks such as transforming the value of scalar fields, e.g. reformat a date. ```graphql type User { @@ -1580,8 +1571,8 @@ enum Role { } ``` -You do not need this directive if the internal value of each enum key -is an identical string. [Read more about enum types](../the-basics/types.md#enum) +You do not need this directive if the internal value of each enum key is an identical string. +[Read more about enum types](../the-basics/types.md#enum) ## @eq @@ -1611,7 +1602,7 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar EqValue ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -1620,8 +1611,7 @@ type User { } ``` -If the name of the argument does not match the database column, -pass the actual column name as the `key`. +If the name of the argument does not match the database column, pass the actual column name as the `key`. ```graphql type User { @@ -1710,8 +1700,7 @@ enum GlobalIdDecode { } ``` -Instead of the original ID, the `id` field will now return a base64-encoded String -that globally identifies the User and can be used for querying the `node` endpoint. +Instead of the original ID, the `id` field will now return a base64-encoded String that globally identifies the User and can be used for querying the `node` endpoint. ```graphql type User { @@ -1720,8 +1709,7 @@ type User { } ``` -The field resolver will receive the decoded version of the passed `id`, -split into type and ID. +The field resolver will receive the decoded version of the passed `id`, split into type and ID. ```graphql type Mutation { @@ -1729,8 +1717,7 @@ type Mutation { } ``` -You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global IDs. +You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global IDs. ## @guard @@ -1765,15 +1752,13 @@ To ensure the user is logged in, add the `AttemptAuthenticate` middleware to you ], ``` -A useful pattern is to group fields in an `extend type` to apply [@guard](#guard) -on all of them at once. +A useful pattern is to group fields in an `extend type` to apply [@guard](#guard) on all of them at once. ```graphql extend type Query @guard { ... } ``` -The [@guard](#guard) directive will be prepended to other directives defined on the fields -and thus executes before them. +The [@guard](#guard) directive will be prepended to other directives defined on the fields and thus executes before them. ```graphql extend type Query { @@ -1859,7 +1844,8 @@ enum HasManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -1886,8 +1872,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model differs from the field name, -you can override it by setting `relation`. +If the relationship name on the Eloquent model differs from the field name, set `relation` to override it. ```graphql type User { @@ -1950,7 +1935,8 @@ enum HasManyThroughType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -1989,8 +1975,7 @@ type User { } ``` -If the name of the relationship on the Eloquent model differs from the field name, -you can override it by setting `relation`. +If the relationship name on the Eloquent model differs from the field name, set `relation` to override it. ```graphql type User { @@ -2024,8 +2009,7 @@ type Mechanic { } ``` -If the name of the relationship on the Eloquent model differs from the field name, -you can override it by setting `relation`. +If the relationship name on the Eloquent model differs from the field name, set `relation` to override it. ```graphql type Mechanic { @@ -2048,7 +2032,8 @@ directive @in( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -2080,8 +2065,8 @@ directive @inject( ) repeatable on FIELD_DEFINITION ``` -This is useful to ensure that the authenticated user's `id` is -automatically used for creating new models and cannot be manipulated. +This ensures the authenticated user `id` is used automatically when creating new models. +It cannot be manipulated by clients. ```graphql type Mutation { @@ -2091,8 +2076,7 @@ type Mutation { } ``` -If you are using an Input Object as an argument, you can use dot notation to -set a nested argument. +If you are using an Input Object as an argument, you can use dot notation to set a nested argument. ```graphql type Mutation { @@ -2118,8 +2102,8 @@ directive @interface( ) on INTERFACE ``` -Make sure you read the [basics about Interfaces](../the-basics/types.md#interface) before deciding -to use this directive, you probably don't need it. +Read the [basics about Interfaces](../the-basics/types.md#interface) before deciding to use this directive. +You probably do not need it. Set the `resolveType` argument to a function that returns the implementing Object Type. @@ -2130,8 +2114,8 @@ interface Commentable } ``` -The function receives the value of the parent field as its single argument and must -return an Object Type. You can get the appropriate Object Type from Lighthouse's type registry. +The function receives the value of the parent field as its single argument and must return an Object Type. +You can get the appropriate Object Type from Lighthouse's type registry. ```php namespace App\GraphQL\Interfaces; @@ -2230,7 +2214,8 @@ directive @like( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ## @limit @@ -2285,8 +2270,7 @@ Lighthouse will return at most the number of results that the client requested. } ``` -If your field is resolved through a database query, you may add the `builder` argument to apply -an actual `LIMIT` clause to your SQL: +If your field is resolved through a database query, you may add the `builder` argument to apply an actual `LIMIT` clause to your SQL: ```graphql type Query { @@ -2334,8 +2318,8 @@ Ensure the order of the argument definition matches the parameters of your metho public function purchasedItemsCount(int $year, ?bool $includeReturns) ``` -Lighthouse will always pass down the same number of arguments and default to `null` -if the client passes nothing. +Lighthouse always passes down the same number of arguments. +It defaults to `null` if the client passes nothing. ```graphql { @@ -2430,7 +2414,8 @@ enum MorphManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -2568,7 +2553,8 @@ enum MorphToManyType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -2589,8 +2575,7 @@ The arguments are a map from directive names to namespaces. directive @namespace repeatable on FIELD_DEFINITION | OBJECT ``` -The following example applies the namespace `App\Blog` -to the [@field](#field) directive used on the `posts` field. +The following example applies the namespace `App\Blog` to the [@field](#field) directive used on the `posts` field. ```graphql type Query { @@ -2600,9 +2585,8 @@ type Query { } ``` -When used upon an object type or an object type extension, the namespace -applies to fields of the type as well. This allows you to specify -a common namespace for a group of fields. +When used upon an object type or an object type extension, the namespace applies to fields of the type as well. +This allows you to specify a common namespace for a group of fields. ```graphql extend type Query @namespace(field: "App\\Blog") { @@ -2660,7 +2644,8 @@ directive @neq( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -2746,8 +2731,7 @@ type Query { } ``` -Lighthouse defaults to resolving types through the underlying model, -for example by calling `User::find($id)`. +Lighthouse defaults to resolving types through the underlying model, for example by calling `User::find($id)`. ```graphql type User @node { @@ -2763,8 +2747,8 @@ type Country @node(resolver: "App\\Countries@byId") { } ``` -The `resolver` argument has to specify a function which will be passed the -decoded `id` and resolves to a result. +The `resolver` argument must specify a function. +It receives the decoded `id` and resolves to a result. ```php public function byId($id): array @@ -2778,8 +2762,8 @@ public function byId($id): array [Read more](../digging-deeper/relay.md#global-object-identification). -Behind the scenes, Lighthouse will decode the global ID sent from the client -to find the model by its primary key in the database. +Behind the scenes, Lighthouse decodes the global ID sent by the client. +It then finds the model by its primary key in the database. ## @notIn @@ -2796,7 +2780,8 @@ directive @notIn( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -2887,7 +2872,8 @@ input OrderByRelation { } ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). See [ordering](../digging-deeper/ordering.md). @@ -2965,7 +2951,8 @@ enum PaginateType { PAGINATOR """ - Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + Offset-based pagination like Laravel "Simple Pagination". + It does not count the total number of records. """ SIMPLE @@ -3058,9 +3045,8 @@ It can be queried like this: ### Pagination type -The `type` of pagination defaults to `PAGINATOR`, -but may also be set to `SIMPLE` (see [Simple Pagination](#simple-pagination)) -or a Relay compliant `CONNECTION`. +The `type` of pagination defaults to `PAGINATOR`. +May also be set to `SIMPLE` (see [Simple Pagination](#simple-pagination)) or a Relay compliant `CONNECTION`. > Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -3105,9 +3091,9 @@ type PostEdge { ### Simple Pagination -In contrast to other pagination types, `SIMPLE` pagination only fires a single database -query on every request. This improves performance, but means that the response does not -hold information about the total number of items. +In contrast to other pagination types, `SIMPLE` pagination fires only one database query per request. +This improves performance. +But means that the response does not hold information about the total number of items. If you wish to use the `simplePaginate` method, set the `type` to `SIMPLE`. @@ -3205,9 +3191,9 @@ query { ### Limit maximum count -Lighthouse allows you to specify a global maximum for the number of items a user -can request through pagination through the config. You may also overwrite this -per field with the `maxCount` argument: +Lighthouse allows you to specify a global maximum for items requested through pagination. +Configure this through the config. +You may also overwrite this per field with the `maxCount` argument: ```graphql type Query { @@ -3217,8 +3203,9 @@ type Query { ### Overwrite model -By default, Lighthouse looks for an Eloquent model in the configured default namespace, with the same -name as the returned type. You can overwrite this by setting the `model` argument. +By default, Lighthouse looks for an Eloquent model in the configured default namespace. +It expects the same name as the returned type. +You can overwrite this by setting the `model` argument. ```graphql type Query { @@ -3236,7 +3223,8 @@ type Query { } ``` -Your method receives the typical resolver arguments and has to return an instance of `Illuminate\Database\Query\Builder`. +Your method receives the typical resolver arguments. +It must return an instance of `Illuminate\Database\Query\Builder`. > If you actually want to query a model and possibly its relations through nested fields, > make sure to return an Eloquent builder, e.g. `Post::query()`. @@ -3264,7 +3252,8 @@ final class Blog You can provide your own function that resolves the field by directly returning data in a `Illuminate\Contracts\Pagination\Paginator` instance. -This is mutually exclusive with `builder` and `model`. Not compatible with `scopes` and builder arguments such as [@eq](#eq). +This is mutually exclusive with `builder` and `model`. +Not compatible with `scopes` and builder arguments such as [@eq](#eq). ```graphql type Query { @@ -3320,8 +3309,7 @@ directive @rename( ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -This can often be useful to ensure consistent naming of your schema -without having to change the underlying models. +This can often be useful to ensure consistent naming of your schema without having to change the underlying models. ```graphql type User { @@ -3525,7 +3513,8 @@ directive @scope( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -3568,12 +3557,10 @@ directive @search( ) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -Requires the installation of [Laravel Scout](https://laravel.com/docs/scout) -and manual registration of the service provider `Nuwave\Lighthouse\Scout\ScoutServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Requires the installation of [Laravel Scout](https://laravel.com/docs/scout) and manual registration of the service provider `Nuwave\Lighthouse\Scout\ScoutServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). -The `search()` method of the model is called with the value of the argument, -using the driver you configured for Scout. +The model `search()` method is called with the argument value. +It uses the Scout driver you configured. ```graphql type Query { @@ -3581,8 +3568,7 @@ type Query { } ``` -The [@search](#search) directive only works in combination with filter directives that -implement the interface `Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: +The [@search](#search) directive only works in combination with filter directives that implement the interface `Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: - [@eq](#eq) - [@softDeletes](#softdeletes) @@ -3590,10 +3576,8 @@ implement the interface `Nuwave\Lighthouse\Scout\ScoutBuilderDirective`: Scout is only activated if an argument annotated with [@search](#search) is present with a string value. Passing `null` behaves the same as leaving the argument out and falls back to a database query. -When using [@convertEmptyStringsToNull](#convertemptystringstonull), nullable `String` arguments with an empty -string value may be converted to `null` and therefore not activate Scout. -If you need empty-string search behavior, prefer an explicit schema contract such as a dedicated search field -or a non-null search argument. +When using [@convertEmptyStringsToNull](#convertemptystringstonull), nullable `String` arguments with an empty string value may be converted to `null` and therefore not activate Scout. +If you need empty-string search behavior, prefer an explicit schema contract such as a dedicated search field or a non-null search argument. Normally the search will be performed using the index specified by the model's `searchableAs` method. However, in some situation a custom index might be needed, this can be achieved by using the argument `within`. @@ -3693,8 +3677,7 @@ mutation { } ``` -Internally, the arguments will be transformed into a flat structure before -they are passed along to the resolver: +Internally, the arguments are transformed into a flat structure before they are passed to the resolver: ```php [ @@ -3704,8 +3687,7 @@ they are passed along to the resolver: ] ``` -Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/field-argument-directives) -have been applied, e.g. validation, transformation. +Note that Lighthouse spreads out the arguments **after** all other [ArgDirectives](../custom-directives/field-argument-directives) have been applied, e.g. validation, transformation. ## @subscription @@ -3722,8 +3704,8 @@ directive @subscription( ) on FIELD_DEFINITION ``` -If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md) -you do not need this directive. It is only useful if you need to override the default namespace. +If you follow the default naming conventions for [defining subscription fields](../subscriptions/defining-fields.md), you do not need this directive. +It is only useful if you need to override the default namespace. ```graphql type Subscription { @@ -3761,11 +3743,12 @@ directive @throttle( ) on FIELD_DEFINITION ``` -Allows use Laravel throttling on a per-field basis. See [Laravel doc](https://laravel.com/docs/routing#rate-limiting) -on how to configure named limiters. +Allows use Laravel throttling on a per-field basis. +See [Laravel doc](https://laravel.com/docs/routing#rate-limiting) on how to configure named limiters. -Limiters that return `response` are not supported. Hashes are different from the ones of Laravel, so one can't use -one named limiter to limit both Laravel route and GraphQL field. +Limiters that return `response` are not supported. +Hashes are different from the ones of Laravel. +So one can't use one named limiter to limit both Laravel route and GraphQL field. ## @trashed @@ -3776,13 +3759,13 @@ Allows to filter if trashed elements should be fetched. directive @trashed on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). The most convenient way to use this directive is through [@softDeletes](#softdeletes). -If you want to add it manually, make sure the argument is of the -enum type `Trashed`: +If you want to add it manually, make sure the argument is of the enum type `Trashed`: ```graphql type Query { @@ -3819,8 +3802,7 @@ type Mutation { } ``` -If you want this for all your fields, consider adding this directive to your -global field middleware in `lighthouse.php`: +If you want this for all your fields, add this directive to your global field middleware in `lighthouse.php`: ```php 'field_middleware' => [ @@ -3845,8 +3827,8 @@ directive @union( ) on UNION ``` -Make sure you read the [basics about Unions](../the-basics/types.md#union) before deciding -to use this directive, you probably don't need it. +Read the [basics about Unions](../the-basics/types.md#union) before deciding to use this directive. +You probably do not need it. ```graphql type User { @@ -3862,8 +3844,8 @@ union Person @union(resolveType: "App\\GraphQL\\Unions\\Person@resolveType") = | Employee ``` -The function receives the value of the parent field as its single argument and must -resolve an Object Type from Lighthouse's `TypeRegistry`. +The function receives the value of the parent field as its single argument. +It must resolve an Object Type from Lighthouse `TypeRegistry`. ```php namespace App\GraphQL\Unions; @@ -3931,8 +3913,8 @@ type Mutation { } ``` -If the name of the Eloquent model does not match the return type of the field, -or is located in a non-default namespace, set it with the `model` argument. +If the name of the Eloquent model does not match the return type of the field, set it with the `model` argument. +If the model is in a non-default namespace, also set it with the `model` argument. ```graphql type Mutation { @@ -4188,7 +4170,8 @@ Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-In scalar WhereValue ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). You can specify simple operators: @@ -4259,10 +4242,11 @@ directive @whereAuth( ) on FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). -The following query returns all posts that belong to the currently authenticated user. +The following query returns all posts that belong to the currently authenticated user. Behind the scenes it is using a `whereHas` query. ```graphql @@ -4289,7 +4273,8 @@ directive @whereBetween( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). This example defines an `input` to filter that a value is between two dates. @@ -4305,8 +4290,8 @@ input DateRange { } ``` -You may use any custom `input` type for the argument. Make sure it has -exactly two required fields to ensure the query is valid. +You may use any custom `input` type for the argument. +Make sure it has exactly two required fields to ensure the query is valid. ## @whereConditions @@ -4331,7 +4316,8 @@ directive @whereJsonContains( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4399,7 +4385,8 @@ directive @whereNotBetween( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4436,7 +4423,8 @@ directive @whereNotNull( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4466,7 +4454,8 @@ directive @whereNull( ) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```graphql @@ -4495,8 +4484,8 @@ directive @with( ) repeatable on FIELD_DEFINITION ``` -This can be a useful optimization for fields that are not returned directly -but rather used for resolving other fields. +This can be a useful optimization for fields that are not returned directly. +It is useful when fields are only used to resolve other fields. ```graphql type User { @@ -4504,7 +4493,7 @@ type User { } ``` -If you just want to return the relation itself as-is, look into [handling Eloquent relationships](../eloquent/relationships.md). +If you just want to return the relation as-is, see [handling Eloquent relationships](../eloquent/relationships.md). ## @withCount @@ -4556,7 +4545,8 @@ directive @withoutGlobalScopes( ) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION ``` -> This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. +> This directive only works when the field resolver passes its builder through +> `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](#all) or [@hasMany](#hasmany). ```php diff --git a/docs/master/api-reference/scalars.md b/docs/master/api-reference/scalars.md index a3016499b5..a06ffb6273 100644 --- a/docs/master/api-reference/scalars.md +++ b/docs/master/api-reference/scalars.md @@ -1,7 +1,6 @@ # Scalars -You can use Lighthouse's built-in scalars by defining them in your schema, -using [@scalar](directives.md#scalar) to point them to a FQCN. +You can use Lighthouse's built-in scalars by defining them in your schema, using [@scalar](directives.md#scalar) to point them to a FQCN. ```graphql "A datetime string with format `Y-m-d H:i:s`, e.g. `2018-05-23 13:43:32`." @@ -66,6 +65,4 @@ scalar Upload This Scalar can only be used as an argument, not as a return type. For more information, please refer to the [file uploads guide](../digging-deeper/file-uploads.md). -The multipart form request is handled by Lighthouse, the resolver gets passed -an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) -in the argument `array $variables`. +The multipart form request is handled by Lighthouse, the resolver gets passed an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) in the argument `array $variables`. diff --git a/docs/master/concepts/arg-resolvers.md b/docs/master/concepts/arg-resolvers.md index a3ce0d91b9..55c88bb130 100644 --- a/docs/master/concepts/arg-resolvers.md +++ b/docs/master/concepts/arg-resolvers.md @@ -1,26 +1,20 @@ # Arg Resolvers -To understand the concept behind arg resolvers, you should familiarize yourself with -[how field resolvers are composed](https://graphql.org/learn/execution). +To understand the concept behind arg resolvers, you should familiarize yourself with [how field resolvers are composed](https://graphql.org/learn/execution). ## Motivation -Arg resolvers are an extension of the ideas behind GraphQL field execution, -applied to input arguments. Since GraphQL queries can be used to fetch complex -and deeply nested data from the client, it is natural to assume that such complex -data can also be passed as the input arguments to a query. +Arg resolvers are an extension of the ideas behind GraphQL field execution, applied to input arguments. +Since GraphQL queries can be used to fetch complex and deeply nested data from the client, it is natural to assume that such complex data can also be passed as the input arguments to a query. -GraphQL's execution engine allows you to write small and focused field resolver functions -that only care about returning the data that it is immediately responsible for. +GraphQL's execution engine allows you to write small and focused field resolver functions that only care about returning the data that it is immediately responsible for. That makes the code much simpler and avoids duplication. -However, a single field resolver still has to take care of all the input arguments that -are passed to it. Handling complex input data in a single function is hard because of their -dynamic nature. The input given by a client might be nested arbitrarily deep -and come in many different variations. +However, a single field resolver still has to take care of all the input arguments that are passed to it. +Handling complex input data in a single function is hard because of their dynamic nature. +The input given by a client might be nested arbitrarily deep and come in many different variations. -The following example shows an example mutation that is actually composed out of multiple -distinct operations. +The following example shows an example mutation that is actually composed out of multiple distinct operations. ```graphql type Mutation { @@ -38,8 +32,7 @@ input CreateNoteInput { } ``` -In a single request, we can pass all data relating to a task, -including related entities such as notes. +In a single request, we can pass all data relating to a task, including related entities such as notes. ```graphql mutation CreateTaskWithNotes { @@ -80,15 +73,13 @@ function createTaskWithNotes(mixed $root, array $args): \App\Models\Task { In this contrived example, the function is still quite small. However, separation of concerns is already violated: A single function is responsible for creating both tasks and notes. -We might want to extend our schema to support more operations in the future, such as updating -a task and creating, updating or deleting notes or other, more deeply nested relations. +We might want to extend our schema to support more operations in the future, such as updating a task and creating, updating or deleting notes or other, more deeply nested relations. Such changes would force us to duplicate code and increase the complexity of our single function. ## Solution -Ideally, we would want to write small and focused functions that deal with just -a part of the given input arguments. The execution engine should traverse the given -input and take care of calling the appropriate functions with their respective arguments. +Ideally, we would want to write small and focused functions that deal with just a part of the given input arguments. +The execution engine should traverse the given input and take care of calling the appropriate functions with their respective arguments. ```php function createTask(mixed $root, array $args): \App\Models\Task { @@ -128,8 +119,7 @@ input CreateNoteInput { The [@create](../api-reference/directives.md#create) directive will behave differently, based on the context where it is used. -On the `createTask` field, it will create a `Task` model with the given `name`, save it -to the database and return that instance to Lighthouse. +On the `createTask` field, it will create a `Task` model with the given `name`, save it to the database and return that instance to Lighthouse. A simplified, generic implementation of an appropriate field resolver would look something like this: @@ -164,8 +154,7 @@ final class CreateDirective extends BaseDirective implements FieldResolver ``` The arguments that are nested within `notes` will be handled as a nested argument resolver. -For each `CreateNoteInput`, the resolver will be called with the previously created `Task` -and create and attach a related `Note` model. +For each `CreateNoteInput`, the resolver will be called with the previously created `Task` and create and attach a related `Note` model. We can extend our previous implementation of [@create](../api-reference/directives.md#create) by allowing it to be used as an `ArgResolver`: diff --git a/docs/master/concepts/request-lifecycle.md b/docs/master/concepts/request-lifecycle.md index 0f02427f5a..e4f9716ea5 100644 --- a/docs/master/concepts/request-lifecycle.md +++ b/docs/master/concepts/request-lifecycle.md @@ -5,8 +5,7 @@ This section should provide an understanding of the involved steps, their order ## Routing -All requests to the configured GraphQL endpoint - usually `/graphql` - are routed -to the single `GraphQLController`. +All requests to the configured GraphQL endpoint - usually `/graphql` - are routed to the single `GraphQLController`. ## HTTP Middleware @@ -27,18 +26,17 @@ This step is typically cached for larger schemas, to enhance performance. ## Query Validation -The GraphQL query is validated to ensure it matches the schema. Lighthouse makes sure the requested -fields are available in the schema, and the correct variables are passed. +The GraphQL query is validated to ensure it matches the schema. +Lighthouse makes sure the requested fields are available in the schema, and the correct variables are passed. ## Field Execution Starting from the root level, the fields within the query are executed. -Each field may be wrapped with field middleware, which can add authentication, authorization, -fine-grained validation, and more. Finally, the field resolver is called to produce a value for the field. +Each field may be wrapped with field middleware, which can add authentication, authorization, fine-grained validation, and more. +Finally, the field resolver is called to produce a value for the field. -If the field contains a subselection, the same process happens for the nested fields, until -we either abort with an error or traversed the entire query tree. +If the field contains a subselection, the same process happens for the nested fields, until we either abort with an error or traversed the entire query tree. [Learn more about GraphQL execution](https://graphql.org/learn/execution). @@ -50,4 +48,5 @@ Lighthouse collects the errors to allow the rest of the query to execute. ## Result Assembly The execution results are assembled into a structure that resembles the query of the client. -Errors are properly formatted and included in the response. The response is sent to the client. +Errors are properly formatted and included in the response. +The response is sent to the client. diff --git a/docs/master/custom-directives/field-argument-directives.md b/docs/master/custom-directives/field-argument-directives.md index 97b7c0e345..d0407f8f88 100644 --- a/docs/master/custom-directives/field-argument-directives.md +++ b/docs/master/custom-directives/field-argument-directives.md @@ -4,11 +4,10 @@ Field argument directives can be applied to field arguments (see [Field Argument ## ArgManipulator -An [`Nuwave\Lighthouse\Support\Contracts\ArgManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgManipulator.php) -directive can be used to manipulate the schema AST of a field argument or its parents. +An [`Nuwave\Lighthouse\Support\Contracts\ArgManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgManipulator.php) directive can be used to manipulate the schema AST of a field argument or its parents. -For example, you might want to add a directive that automagically derives the arguments -for a field based on an object type. A skeleton for this directive might look something like this: +For example, you might want to add a directive that automagically derives the arguments for a field based on an object type. +A skeleton for this directive might look something like this: ```php namespace App\GraphQL\Directives; diff --git a/docs/master/custom-directives/field-directives.md b/docs/master/custom-directives/field-directives.md index 91da872947..fefe8bf3d4 100644 --- a/docs/master/custom-directives/field-directives.md +++ b/docs/master/custom-directives/field-directives.md @@ -4,18 +4,15 @@ Field directives can be applied to any [FieldDefinition](https://graphql.github. ## FieldResolver -Perhaps the most important directive interface, a [`Nuwave\Lighthouse\Support\Contracts\FieldResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldResolver.php) -lets you add a resolver for a field through a directive. +Perhaps the most important directive interface, a [`Nuwave\Lighthouse\Support\Contracts\FieldResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldResolver.php) lets you add a resolver for a field through a directive. It can be a great way to reuse resolver logic within a schema. ## FieldMiddleware -A [`Nuwave\Lighthouse\Support\Contracts\FieldMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldMiddleware.php) directive allows you -to wrap around the field resolver, just like [Laravel Middleware](https://laravel.com/docs/middleware). +A [`Nuwave\Lighthouse\Support\Contracts\FieldMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldMiddleware.php) directive allows you to wrap around the field resolver, just like [Laravel Middleware](https://laravel.com/docs/middleware). -You may use it to handle incoming values before reaching the final resolver -as well as the outgoing result of resolving the field. +You may use it to handle incoming values before reaching the final resolver as well as the outgoing result of resolving the field. ```php namespace App\GraphQL\Directives; @@ -64,8 +61,7 @@ type Query { ## FieldBuilderDirective -A [`Nuwave\Lighthouse\Support\Contracts\FieldBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/FieldBuilderDirective.php) -directive allows modifying the database query that Lighthouse creates for a field. +A [`Nuwave\Lighthouse\Support\Contracts\FieldBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/FieldBuilderDirective.php) directive allows modifying the database query that Lighthouse creates for a field. > This directive only works if the field resolver passes its builder through a call to `$resolveInfo->enhanceBuilder()`. > Built-in field resolver directives that query the database do this, such as [@all](../api-reference/directives.md#all) or [@hasMany](../api-reference/directives.md#hasmany). @@ -76,17 +72,14 @@ The following directives use the defined filter for resolving the query: ## FieldManipulator -A [`Nuwave\Lighthouse\Support\Contracts\FieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldManipulator.php) -directive can be used to manipulate the schema AST. +A [`Nuwave\Lighthouse\Support\Contracts\FieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/FieldManipulator.php) directive can be used to manipulate the schema AST. ## ValidationDirective -This directive type is implemented as an abstract class rather than a pure interface and allows -you to define complex validation rules for a field with ease. +This directive type is implemented as an abstract class rather than a pure interface and allows you to define complex validation rules for a field with ease. [Read more about it in the Validation section](../security/validation.md#validator-for-fields). ## ComplexityResolverDirective -A [`Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ComplexityResolverDirective.php) -directive allows you to overwrite the default query complexity calculation. +A [`Nuwave\Lighthouse\Support\Contracts\ComplexityResolverDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ComplexityResolverDirective.php) directive allows you to overwrite the default query complexity calculation. diff --git a/docs/master/custom-directives/getting-started.md b/docs/master/custom-directives/getting-started.md index cef16eab8a..42959b95c0 100644 --- a/docs/master/custom-directives/getting-started.md +++ b/docs/master/custom-directives/getting-started.md @@ -20,8 +20,7 @@ Use the artisan generator command to create it: php artisan lighthouse:directive --argument upperCase ``` -That will create a class called `UpperCaseDirective` that extends the -abstract class `Nuwave\Lighthouse\Schema\Directives\BaseDirective`. +That will create a class called `UpperCaseDirective` that extends the abstract class `Nuwave\Lighthouse\Schema\Directives\BaseDirective`. ```php use Nuwave\Lighthouse\Schema\Directives\BaseDirective; @@ -95,13 +94,12 @@ It is advised to look at the Lighthouse source code to find directives that impl Now that we defined and implemented the directive, how can Lighthouse find it? -When Lighthouse encounters a directive within the schema, it starts looking for a matching class -in the following order: +When Lighthouse encounters a directive within the schema, it starts looking for a matching class in the following order: 1. User-defined namespaces as configured in `config/lighthouse.php`, defaults to `App\GraphQL\Directives` 1. The [RegisterDirectiveNamespaces](../api-reference/events.md#registerdirectivenamespaces) event is dispatched to gather namespaces defined by plugins, extensions or other listeners 1. Lighthouse's built-in directive namespace -This means that our directive is already registered, just by matter of defining it in the default namespace, -and will take precedence over potential other directives with the same name. +This means that our directive is already registered, just by matter of defining it in the default namespace. +Will take precedence over potential other directives with the same name. diff --git a/docs/master/custom-directives/input-field-directives.md b/docs/master/custom-directives/input-field-directives.md index 2a0ff6f98c..8e7b6b5553 100644 --- a/docs/master/custom-directives/input-field-directives.md +++ b/docs/master/custom-directives/input-field-directives.md @@ -4,8 +4,7 @@ Input field directives can be applied to input fields (see [InputFieldsDefinitio ## InputFieldManipulator -An [`Nuwave\Lighthouse\Support\Contracts\InputFieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/InputFieldManipulator.php) -directive can be used to manipulate the schema AST of an input field or its parent. +An [`Nuwave\Lighthouse\Support\Contracts\InputFieldManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/InputFieldManipulator.php) directive can be used to manipulate the schema AST of an input field or its parent. For example, the following directive automatically adds translations for the input field description. diff --git a/docs/master/custom-directives/input-value-directives.md b/docs/master/custom-directives/input-value-directives.md index e1668b7c18..0fb891b5e6 100644 --- a/docs/master/custom-directives/input-value-directives.md +++ b/docs/master/custom-directives/input-value-directives.md @@ -2,8 +2,7 @@ Some directives can be applied to field arguments or input fields (any [InputValueDefinition](https://graphql.github.io/graphql-spec/June2018/#InputValueDefinition)). -As arguments may be contained within a list in the schema definition, you must specify -what your directive should apply to in addition to its function. +As arguments may be contained within a list in the schema definition, you must specify what your directive should apply to in addition to its function. - If it applies to the individual items within the list, implement the [`Nuwave\Lighthouse\Support\Contracts\ArgDirective`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgDirective.php) interface. @@ -14,8 +13,7 @@ You must implement exactly one of those two interfaces in order for an argument ## Evaluation Order -The application of directives that implement the `ArgDirective` interface is -split into three distinct phases: +The application of directives that implement the `ArgDirective` interface is split into three distinct phases: - Sanitize: Clean the input, e.g. trim whitespace. Directives can hook into this phase by implementing `ArgSanitizerDirective`. @@ -39,8 +37,7 @@ In the given example, Lighthouse will take the value of the `password` argument ## ArgSanitizerDirective -An [`Nuwave\Lighthouse\Support\Contracts\ArgSanitizerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgSanitizerDirective.php) -takes an incoming value and returns a new value. +An [`Nuwave\Lighthouse\Support\Contracts\ArgSanitizerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgSanitizerDirective.php) takes an incoming value and returns a new value. Let's take a look at the built-in [@trim](../api-reference/directives.md#trim) directive. @@ -74,8 +71,8 @@ final class TrimDirective extends BaseDirective implements ArgSanitizerDirective } ``` -The `sanitize` method takes an argument which represents the actual incoming value that is given -to an argument in a query and is expected to modify the value, if needed, and return it. +The `sanitize` method takes an argument which represents the actual incoming value that is given to an argument in a query and is expected to modify the value, if needed. +Return it. For example, if we have the following schema. @@ -106,8 +103,7 @@ final class CreateUser ## ArgTransformerDirective -An [`Nuwave\Lighthouse\Support\Contracts\ArgTransformerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgTransformerDirective.php) -works essentially the same as an [`ArgSanitizerDirective`](#argsanitizerdirective). +An [`Nuwave\Lighthouse\Support\Contracts\ArgTransformerDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgTransformerDirective.php) works essentially the same as an [`ArgSanitizerDirective`](#argsanitizerdirective). Notable differences are: - The method to implement is called `transform` @@ -115,9 +111,7 @@ Notable differences are: ## ArgBuilderDirective -An [`Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgBuilderDirective.php) -directive allows using arguments passed by the client to dynamically -modify the database query that Lighthouse creates for a field. +An [`Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective`](https://github.com/nuwave/lighthouse/blob/master/src/Support/Contracts/ArgBuilderDirective.php) directive allows using arguments passed by the client to dynamically modify the database query that Lighthouse creates for a field. Currently, the following directives use arguments to modify the query: @@ -139,8 +133,7 @@ type User { } ``` -Passing the `category` argument will select only the user's posts -where the `category` column is equal to the value of the `category` argument. +Passing the `category` argument will select only the user's posts where the `category` column is equal to the value of the `category` argument. So let's take a look at a simplified version of the built-in [@eq](../api-reference/directives.md#eq) directive. @@ -188,8 +181,7 @@ The `handleBuilder` method takes two arguments: - `$value` The value of the argument value that [@eq](../api-reference/directives.md#eq) was applied on to. -If you want to use a more complex value for manipulating a query, -you can build a `ArgBuilderDirective` to work with lists or nested input objects. +If you want to use a more complex value for manipulating a query, you can build a `ArgBuilderDirective` to work with lists or nested input objects. Lighthouse's [@whereBetween](../api-reference/directives.md#wherebetween) is one example of this. ```graphql @@ -206,9 +198,6 @@ input DateRange { ## ArgResolver -An [`Nuwave\Lighthouse\Support\Contracts\ArgResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgResolver.php) -directive allows you to compose resolvers for complex nested inputs, similar to the way -that field resolvers are composed together. +An [`Nuwave\Lighthouse\Support\Contracts\ArgResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/ArgResolver.php) directive allows you to compose resolvers for complex nested inputs, similar to the way that field resolvers are composed together. -For an in-depth explanation of the concept of composing arg resolvers, -read the [explanation of arg resolvers](../concepts/arg-resolvers.md). +For an in-depth explanation of the concept of composing arg resolvers, read the [explanation of arg resolvers](../concepts/arg-resolvers.md). diff --git a/docs/master/custom-directives/type-directives.md b/docs/master/custom-directives/type-directives.md index 4a84dd2182..f562f6b523 100644 --- a/docs/master/custom-directives/type-directives.md +++ b/docs/master/custom-directives/type-directives.md @@ -6,18 +6,15 @@ These directives can generally be applied to [type definitions](../the-basics/ty ## TypeManipulator -The [`Nuwave\Lighthouse\Support\Contracts\TypeManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeManipulator.php) -interface can be used to manipulate the AST from a type definition node. +The [`Nuwave\Lighthouse\Support\Contracts\TypeManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeManipulator.php) interface can be used to manipulate the AST from a type definition node. ## TypeMiddleware -The [`Nuwave\Lighthouse\Support\Contracts\TypeMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeMiddleware.php) -interface allows access to an AST node as it is converted to an executable type. +The [`Nuwave\Lighthouse\Support\Contracts\TypeMiddleware`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeMiddleware.php) interface allows access to an AST node as it is converted to an executable type. ## TypeResolver -The [`Nuwave\Lighthouse\Support\Contracts\TypeResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeResolver.php) -interface can be used for custom conversion from AST values to an executable type. +The [`Nuwave\Lighthouse\Support\Contracts\TypeResolver`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeResolver.php) interface can be used for custom conversion from AST values to an executable type. ## Type Extension Directives @@ -25,5 +22,4 @@ These directives can generally be applied to [type extensions](https://graphql.g ## TypeExtensionManipulator -The [`Nuwave\Lighthouse\Support\Contracts\TypeExtensionManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeExtensionManipulator.php) -interface can be used to manipulate the AST from a type extension node. +The [`Nuwave\Lighthouse\Support\Contracts\TypeExtensionManipulator`](https://github.com/nuwave/lighthouse/tree/master/src/Support/Contracts/TypeExtensionManipulator.php) interface can be used to manipulate the AST from a type extension node. diff --git a/docs/master/digging-deeper/adding-types-programmatically.md b/docs/master/digging-deeper/adding-types-programmatically.md index e1965d5eef..80d2a55a61 100644 --- a/docs/master/digging-deeper/adding-types-programmatically.md +++ b/docs/master/digging-deeper/adding-types-programmatically.md @@ -4,9 +4,7 @@ You might want to add additional types to the schema programmatically. ## Additional Schema Definitions -If you want to use the SDL to define additional types dynamically, -you can listen for the [`BuildSchemaString`](../api-reference/events.md#buildschemastring) -event and return additional schema definitions as a string: +If you want to use the SDL to define additional types dynamically, you can listen for the [`BuildSchemaString`](../api-reference/events.md#buildschemastring) event and return additional schema definitions as a string: ```php $dispatcher = app(\Illuminate\Contracts\Events\Dispatcher::class); @@ -18,8 +16,7 @@ $dispatcher->listen( ); ``` -When your schema is defined within files and you want to use `#import` to combine them, -you can use the `Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: +When your schema is defined within files and you want to use `#import` to combine them, you can use the `Nuwave\Lighthouse\Schema\Source\SchemaStitcher` to load your file: ```php $stitcher = new \Nuwave\Lighthouse\Schema\Source\SchemaStitcher(__DIR__ . '/path/to/schema.graphql'); @@ -30,11 +27,9 @@ return $stitcher->getSchemaString(); While Lighthouse is an SDL-first GraphQL server, you can also use native PHP type definitions. -Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) -on how to define types. +Check out the [webonyx/graphql-php documentation](https://webonyx.github.io/graphql-php/type-definitions) on how to define types. -Note that you will not have access to a large portion of Lighthouse functionality -that is provided through server-side directives and the definition is much more verbose. +Note that you will not have access to a large portion of Lighthouse functionality that is provided through server-side directives and the definition is much more verbose. Because of this, we do not recommend you use native PHP types for complex object types. diff --git a/docs/master/digging-deeper/client-directives.md b/docs/master/digging-deeper/client-directives.md index 8e45e19ef6..3bf598a75f 100644 --- a/docs/master/digging-deeper/client-directives.md +++ b/docs/master/digging-deeper/client-directives.md @@ -4,17 +4,16 @@ Client directives allow clients to change the behavior of query execution. > Client directives must not be used within your schema definition. -The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) -mentions two client directives: [@skip](#skip) and [@include](#include). +The [GraphQL specification](https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives) mentions two client directives. +[@skip](#skip) and [@include](#include). Both are built-in to Lighthouse and work out-of-the-box. ## @skip -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional -exclusion during execution as described by the `if` argument. +The [@skip](#skip) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional exclusion during execution as described by the `if` argument. ```graphql directive @skip( @@ -36,11 +35,10 @@ query myQuery($someTest: Boolean) { ## @include -This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) -and is built-in to Lighthouse. +This directive is part of the [GraphQL spec](https://graphql.github.io/graphql-spec/June2018/#sec--include) and is built-in to Lighthouse. -The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments, -and allows for conditional inclusion during execution as described by the `if` argument. +The [@include](#include) directive may be provided for fields, fragment spreads, and inline fragments. +Allows for conditional inclusion during execution as described by the `if` argument. ```graphql directive @include( @@ -74,19 +72,17 @@ directive @example( ``` By itself, a custom client directive does not do anything. -Lighthouse provides a class to retrieve information about where client directives -were placed in the query and what arguments were given to them. +Lighthouse provides a class to retrieve information about where client directives were placed in the query and what arguments were given to them. ```php $clientDirective = new \Nuwave\Lighthouse\ClientDirectives\ClientDirective('example'); ``` -The most common use case for a client directive is to place it on a field. There is a caveat -to working with this that is unintuitive at first: There might be multiple nodes referencing a single -field, and each of those may or may not have the client directive set, with possibly different arguments. +The most common use case for a client directive is to place it on a field. +There is a caveat to working with this that is unintuitive at first: There might be multiple nodes referencing a single field. +Each of those may or may not have the client directive set, with possibly different arguments. -The following example illustrates how a field `foo` can be referenced three times with different -configurations of a client directive: +The following example illustrates how a field `foo` can be referenced three times with different configurations of a client directive: ```graphql { @@ -98,8 +94,7 @@ configurations of a client directive: } ``` -You can get all arguments for every node that is referencing the field you are currently -resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): +You can get all arguments for every node that is referencing the field you are currently resolving, passing the fourth [resolver argument `ResolveInfo $resolveInfo`](../api-reference/resolvers.md#resolver-function-signature): ```php $arguments = $clientDirective->forField($resolveInfo); @@ -116,8 +111,8 @@ For the example query above, it will look like this: ] ``` -You are then free to implement whatever logic on top of that. Some client directives may require -only one field node to have it set, whereas others might require all of them to have the same configuration. +You are then free to implement whatever logic on top of that. +Some client directives may require only one field node to have it set, whereas others might require all of them to have the same configuration. > There are other locations where client directives may be used on: https://spec.graphql.org/draft/#ExecutableDirectiveLocation > You can add a PR to Lighthouse if you need them. diff --git a/docs/master/digging-deeper/deprecation.md b/docs/master/digging-deeper/deprecation.md index 3a51c91688..27bf0d2e96 100644 --- a/docs/master/digging-deeper/deprecation.md +++ b/docs/master/digging-deeper/deprecation.md @@ -1,7 +1,6 @@ # Deprecation -The [@deprecated](../api-reference/directives.md#deprecated) directive allows marking elements -of a GraphQL schema as deprecated. +The [@deprecated](../api-reference/directives.md#deprecated) directive allows marking elements of a GraphQL schema as deprecated. ## Detect deprecated usage @@ -10,8 +9,8 @@ of a GraphQL schema as deprecated. Before you eventually remove deprecated elements, you want to give clients time to switch over. To be sure the elements are no longer in use, dynamic instrumentation is required. -Lighthouse allows you to register a handler function that is called with a list of deprecated -elements that were used in a query. Use a reporting mechanism of your choice to get notified. +Lighthouse allows you to register a handler function that is called with a list of deprecated elements that were used in a query. +Use a reporting mechanism of your choice to get notified. In order to not slow down your response times, use a terminating callback. ```php diff --git a/docs/master/digging-deeper/error-handling.md b/docs/master/digging-deeper/error-handling.md index 2d019500c0..9e8a663c0a 100644 --- a/docs/master/digging-deeper/error-handling.md +++ b/docs/master/digging-deeper/error-handling.md @@ -1,16 +1,15 @@ # Error Handling -Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**, -so you can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). +Most of the error handling in Lighthouse is pretty closely based upon **webonyx/graphql-php**. +You can find a lot of valuable information [in their documentation](https://webonyx.github.io/graphql-php/error-handling). ## User-friendly Errors -In a production setting, error messages should not be shown to the user by default -to prevent information leaking. In some cases however, you may want to display an -explicit error message to the user. +In a production setting, error messages should not be shown to the user by default to prevent information leaking. +In some cases however, you may want to display an explicit error message to the user. -**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface, that can -be implemented by Exceptions to control how they are rendered to the client. +**webonyx/graphql-php** offers the [`GraphQL\Error\ClientAware`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ClientAware.php) interface. +Can be implemented by Exceptions to control how they are rendered to the client. Head over their [Error Handling docs](https://webonyx.github.io/graphql-php/error-handling) to learn more. @@ -18,8 +17,7 @@ Head over their [Error Handling docs](https://webonyx.github.io/graphql-php/erro Lighthouse will catch exceptions thrown during the execution of a query and return them as part of the response. -The error handler `Nuwave\Lighthouse\Execution\ReportingErrorHandler` is included in the default configuration -and reports non-client-safe errors through the default Laravel exception handler. +The error handler `Nuwave\Lighthouse\Execution\ReportingErrorHandler` is included in the default configuration and reports non-client-safe errors through the default Laravel exception handler. Client-safe errors are assumed to be something that: @@ -28,8 +26,7 @@ Client-safe errors are assumed to be something that: Thus, they are typically not actionable for server developers. -However, you can choose to report client-safe errors by replacing `Nuwave\Lighthouse\Execution\ReportingErrorHandler` -with `Nuwave\Lighthouse\Execution\AlwaysReportingErrorHandler` in the `lighthouse.php` config: +However, you can choose to report client-safe errors by replacing `Nuwave\Lighthouse\Execution\ReportingErrorHandler` with `Nuwave\Lighthouse\Execution\AlwaysReportingErrorHandler` in the `lighthouse.php` config: ```diff 'error_handlers' => [ @@ -42,8 +39,7 @@ with `Nuwave\Lighthouse\Execution\AlwaysReportingErrorHandler` in the `lighthous ## Additional Error Information -The interface [`GraphQL\Error\ProvidesExtensions`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ProvidesExtensions.php) -may be implemented to add more information than just an error message to the rendered error output. +The interface [`GraphQL\Error\ProvidesExtensions`](https://github.com/webonyx/graphql-php/blob/master/src/Error/ProvidesExtensions.php) may be implemented to add more information than just an error message to the rendered error output. This custom exception contains information about the reason the exception was thrown: @@ -89,8 +85,7 @@ final class CustomException extends Exception implements ClientAware, ProvidesEx } ``` -Now you can throw that Exception somewhere in your code, for example in your resolver, -and it will display additional error output. +Now you can throw that Exception somewhere in your code, for example in your resolver, and it will display additional error output. ```php namespace App\GraphQL\Queries; @@ -174,11 +169,9 @@ final class CountErrorHandler implements ErrorHandler ## Partial Errors -As a GraphQL query may return a partial result, you may not always want to abort -execution immediately after an error occurred. +As a GraphQL query may return a partial result, you may not always want to abort execution immediately after an error occurred. -Use the [`ErrorPool`](https://github.com/nuwave/lighthouse/blob/master/src/Execution/ErrorPool.php) -when you want to collect multiple errors before returning a result. +Use the [`ErrorPool`](https://github.com/nuwave/lighthouse/blob/master/src/Execution/ErrorPool.php) when you want to collect multiple errors before returning a result. ```php try { diff --git a/docs/master/digging-deeper/extending-lighthouse.md b/docs/master/digging-deeper/extending-lighthouse.md index 5bbc66bef2..0b4aa5e4e8 100644 --- a/docs/master/digging-deeper/extending-lighthouse.md +++ b/docs/master/digging-deeper/extending-lighthouse.md @@ -4,8 +4,7 @@ Lighthouse offers various extension points which can be used by package and appl ## The Event System -Lighthouse offers a unified way of hooking into the complete execution lifecycle -through [Laravel's event system](https://laravel.com/docs/events). +Lighthouse offers a unified way of hooking into the complete execution lifecycle through [Laravel's event system](https://laravel.com/docs/events). You may use any Service Provider to register listeners. A complete list of all dispatched events is available [in the events API reference](../api-reference/events.md). @@ -35,8 +34,7 @@ final class SomePackageServiceProvider extends ServiceProvider ## Changing the default resolver -Lighthouse will fall back to using [webonyx's default resolver](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver) -for non-root fields, [see resolver precedence](../the-basics/fields.md#resolver-precedence). +Lighthouse will fall back to using [webonyx's default resolver](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver) for non-root fields, [see resolver precedence](../the-basics/fields.md#resolver-precedence). You may override this by calling `GraphQL\Executor\Executor::setDefaultFieldResolver()` in your service provider's `boot()` method. @@ -44,8 +42,7 @@ You may override this by calling `GraphQL\Executor\Executor::setDefaultFieldReso The context is the third argument of any resolver function. -You may replace the default `Nuwave\Lighthouse\Schema\Context` with your own -implementation of the interface `Nuwave\Lighthouse\Support\Contracts\GraphQLContext`. +You may replace the default `Nuwave\Lighthouse\Schema\Context` with your own implementation of the interface `Nuwave\Lighthouse\Support\Contracts\GraphQLContext`. The following example is just a starting point of what you can do: ```php diff --git a/docs/master/digging-deeper/feature-toggles.md b/docs/master/digging-deeper/feature-toggles.md index fe4e56587e..578ea8bdbe 100644 --- a/docs/master/digging-deeper/feature-toggles.md +++ b/docs/master/digging-deeper/feature-toggles.md @@ -4,11 +4,10 @@ Lighthouse allows you to conditionally show or hide elements (fields, types, arg ## @show and @hide -The directives [@show](../api-reference/directives.md#show) and [@hide](../api-reference/directives.md#hide) -work in a similar way, but are logical opposites of each other. +The directives [@show](../api-reference/directives.md#show) and [@hide](../api-reference/directives.md#hide) work in a similar way. +Are logical opposites of each other. -For example, you might want to limit an experimental new field to test environments. -[@show](../api-reference/directives.md#show) is most suitable for this: +For example, you might want to limit an experimental new field to test environments. [@show](../api-reference/directives.md#show) is most suitable for this: ```graphql type Query { @@ -27,8 +26,7 @@ type Query { ## @feature -The [@feature](../api-reference/directives.md#feature) directive allows to include fields, types, arguments, or input fields in the schema -depending on whether a [Laravel Pennant](https://laravel.com/docs/pennant) feature is active. +The [@feature](../api-reference/directives.md#feature) directive allows to include fields, types, arguments, or input fields in the schema depending on whether a [Laravel Pennant](https://laravel.com/docs/pennant) feature is active. For example, you might want a new experimental field only to be available when the according feature is active: @@ -48,8 +46,7 @@ type Query { } ``` -When using [class based features](https://laravel.com/docs/pennant#class-based-features), -the fully qualified class name must be used as the value for the `name` argument: +When using [class based features](https://laravel.com/docs/pennant#class-based-features), the fully qualified class name must be used as the value for the `name` argument: ```graphql type Query { @@ -59,8 +56,7 @@ type Query { ## Conditional Type Inclusion -When you conditionally include a type using [@show](../api-reference/directives.md#show), [@hide](../api-reference/directives.md#hide) or [@feature](../api-reference/directives.md#feature), -any fields using it must also be conditionally included. +When you conditionally include a type using [@show](../api-reference/directives.md#show), [@hide](../api-reference/directives.md#hide) or [@feature](../api-reference/directives.md#feature), any fields using it must also be conditionally included. If the type is omitted but still used somewhere, the schema will be invalid. ```graphql @@ -76,11 +72,9 @@ type Query { ## Interaction With Schema Cache [@show](../api-reference/directives.md#show) and [@hide](../api-reference/directives.md#hide) work by manipulating the schema. -This means that when using their `env` option, the inclusion or exclusion of elements depends on the value -of `app()->environment()` at the time the schema is built and not update on later environment changes. +This means that when using their `env` option, the inclusion or exclusion of elements depends on the value of `app()->environment()` at the time the schema is built and not update on later environment changes. If you are pre-generating your schema cache, make sure to match the environment to your deployment target. -The same goes for [@feature](../api-reference/directives.md#feature). Whether a field is included in the schema will be -based on the state of a feature at the time the schema is built. In addition, if you are pre-generating your schema cache, -you will only be able to use features that support [nullable scopes](https://laravel.com/docs/pennant#nullable-scope), -as there won't be an authenticated user to check the feature against. +The same goes for [@feature](../api-reference/directives.md#feature). +Whether a field is included in the schema will be based on the state of a feature at the time the schema is built. +In addition, if you are pre-generating your schema cache, you will only be able to use features that support [nullable scopes](https://laravel.com/docs/pennant#nullable-scope), as there won't be an authenticated user to check the feature against. diff --git a/docs/master/digging-deeper/file-uploads.md b/docs/master/digging-deeper/file-uploads.md index bfafc1179f..b881ca9d81 100644 --- a/docs/master/digging-deeper/file-uploads.md +++ b/docs/master/digging-deeper/file-uploads.md @@ -1,7 +1,6 @@ # Uploading files -Lighthouse allows you to upload files using a multipart form request -as defined in [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec). +Lighthouse allows you to upload files using a multipart form request as defined in [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec). ## Setup @@ -25,11 +24,9 @@ type Mutation { ## Handling file uploads Lighthouse accepts multipart form requests that contain file uploads. -The given file is injected into the `array $variables` as an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) -and passed into the resolver. +The given file is injected into the `array $variables` as an instance of [`Illuminate\Http\UploadedFile`](https://laravel.com/api/9.x/Illuminate/Http/UploadedFile.html) and passed into the resolver. -It is up to you how to handle the given file in the resolver, -see the [Laravel docs for File Uploads](https://laravel.com/docs/filesystem#file-uploads). +It is up to you how to handle the given file in the resolver, see the [Laravel docs for File Uploads](https://laravel.com/docs/filesystem#file-uploads). The field from the previous example can be implemented like this: @@ -56,8 +53,7 @@ final class Upload ## Client-side Usage In order to upload a file, you must send a `multipart/form-data` request. -Use any of the [available client implementations](https://github.com/jaydenseric/graphql-multipart-request-spec#client) -or look at the [specification examples](https://github.com/jaydenseric/graphql-multipart-request-spec#multipart-form-field-structure) to roll your own. +Use any of the [available client implementations](https://github.com/jaydenseric/graphql-multipart-request-spec#client) or look at the [specification examples](https://github.com/jaydenseric/graphql-multipart-request-spec#multipart-form-field-structure) to roll your own. > If you are using [the EnsureXHR middleware to protect against CSRF](../security/csrf.md), > add the header `X-Requested-With: XMLHttpRequest` to your request. diff --git a/docs/master/digging-deeper/ordering.md b/docs/master/digging-deeper/ordering.md index 175141ef5a..5c9819882b 100644 --- a/docs/master/digging-deeper/ordering.md +++ b/docs/master/digging-deeper/ordering.md @@ -2,8 +2,7 @@ ## Client Controlled Ordering -To enable clients to control the ordering, use [@orderBy](../api-reference/directives.md#orderby) on an argument of -a field that is backed by a database query. +To enable clients to control the ordering, use [@orderBy](../api-reference/directives.md#orderby) on an argument of a field that is backed by a database query. ```graphql type Query { @@ -11,9 +10,8 @@ type Query { } ``` -The type of the argument can be left blank as `_` , -as Lighthouse will automatically generate an input that takes enumerated column names, -together with the `SortOrder` enum, and add that to your schema: +The type of the argument can be left blank as `_` , as Lighthouse will automatically generate an input that takes enumerated column names, together with the `SortOrder` enum. +Add that to your schema: ```graphql "Order by clause for Query.posts.orderBy." diff --git a/docs/master/digging-deeper/relay.md b/docs/master/digging-deeper/relay.md index c9811ac345..a8b4e3b23a 100644 --- a/docs/master/digging-deeper/relay.md +++ b/docs/master/digging-deeper/relay.md @@ -2,9 +2,8 @@ ## Cursor Connection -Relay requires a particular kind of pagination which is the [Cursor Connection](https://facebook.github.io/relay/graphql/connections.htm) -To get a relay-compatible connection on a root query field, use the [@paginate](../api-reference/directives.md#paginate) -directive with the pagination type `CONNECTION`. +Relay requires a particular kind of pagination which is the [Cursor Connection](https://facebook.github.io/relay/graphql/connections.htm). +To get a relay-compatible connection on a root query field, use the [@paginate](../api-reference/directives.md#paginate) directive with the pagination type `CONNECTION`. > Lighthouse does not support actual cursor-based pagination as of now, see https://github.com/nuwave/lighthouse/issues/311 for details. > Under the hood, the "cursor" is decoded into a page offset. @@ -15,11 +14,10 @@ type Query { } ``` -This automatically converts the type definition into a relay connection and constructs -the appropriate queries via the underlying Eloquent model. +This automatically converts the type definition into a relay connection and constructs the appropriate queries via the underlying Eloquent model. -Connections can also be used for subfields of a type, given they are defined as a HasMany-Relationship -in Eloquent. Use the [@hasMany](../api-reference/directives.md#hasmany) directive. +Connections can also be used for subfields of a type, given they are defined as a HasMany-Relationship in Eloquent. +Use the [@hasMany](../api-reference/directives.md#hasmany) directive. ```graphql type User { @@ -30,8 +28,7 @@ type User { ## Global Object Identification -You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your -own mechanism of encoding/decoding global IDs. +You may rebind the `Nuwave\Lighthouse\Support\Contracts\GlobalId` interface to add your own mechanism of encoding/decoding global IDs. [Global Object Identification](https://relay.dev/graphql/objectidentification.htm) diff --git a/docs/master/digging-deeper/schema-organisation.md b/docs/master/digging-deeper/schema-organisation.md index fc97d49851..07598310b0 100644 --- a/docs/master/digging-deeper/schema-organisation.md +++ b/docs/master/digging-deeper/schema-organisation.md @@ -45,8 +45,7 @@ graphql/ |-- category.graphql ``` -To import all schema files in `blog/` in one go, use wildcard import syntax -(works like PHP's [glob function](https://php.net/manual/function.glob.php)). +To import all schema files in `blog/` in one go, use wildcard import syntax (works like PHP's [glob function](https://php.net/manual/function.glob.php)). ```graphql #import blog/*.graphql @@ -70,11 +69,10 @@ The definition is imported from `schema.graphql`: ``` Now you want to add queries to allow fetching posts. -While you could add it to the main `Query` type in `schema.graphql`, -it is generally preferable to colocate queries with the type they return. +While you could add it to the main `Query` type in `schema.graphql`, it is generally preferable to colocate queries with the type they return. -Make sure `schema.graphql` contains a `Query` type. You can add an empty type -if you don't have one there: +Make sure `schema.graphql` contains a `Query` type. +You can add an empty type if you don't have one there: ```graphql type Query @@ -95,5 +93,4 @@ extend type Query { The fields in the `extend type` definition are merged with those of the original type. Apart from object types `type`, you can also extend `input`, `interface` and `enum` types. -Lighthouse will merge the fields (or values) with the original definition and always -produce a single type in the final schema. +Lighthouse will merge the fields (or values) with the original definition and always produce a single type in the final schema. diff --git a/docs/master/eloquent/complex-where-conditions.md b/docs/master/eloquent/complex-where-conditions.md index 4c6579b506..b45538e493 100644 --- a/docs/master/eloquent/complex-where-conditions.md +++ b/docs/master/eloquent/complex-where-conditions.md @@ -2,10 +2,8 @@ **Experimental: not enabled by default, not guaranteed to be stable.** -Adding query conditions ad-hoc can be cumbersome and limiting when you require -manifold ways to filter query results. -Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients -and allow them to apply complex, dynamic WHERE conditions to queries. +Adding query conditions ad-hoc can be cumbersome and limiting when you require manifold ways to filter query results. +Lighthouse's `WhereConditions` extension can give advanced query capabilities to clients and allow them to apply complex, dynamic WHERE conditions to queries. ## Setup @@ -18,8 +16,7 @@ return [ ] ``` -For other versions, register the service provider `Nuwave\Lighthouse\WhereConditions\WhereConditionsServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +For other versions, register the service provider `Nuwave\Lighthouse\WhereConditions\WhereConditionsServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). Install the dependency [mll-lab/graphql-php-scalars](https://github.com/mll-lab/graphql-php-scalars): @@ -29,8 +26,7 @@ composer require mll-lab/graphql-php-scalars ## Usage -You can use this feature through a set of schema directives that enhance fields -with advanced filter capabilities. +You can use this feature through a set of schema directives that enhance fields with advanced filter capabilities. ### @whereConditions @@ -89,8 +85,8 @@ type Person { } ``` -Lighthouse automatically generates definitions for an `Enum` type and an `Input` type -that are restricted to the defined columns, so you do not have to specify them by hand. +Lighthouse automatically generates definitions for an `Enum` type and an `Input` type that are restricted to the defined columns. +You do not have to specify them by hand. The blank type named `_` will be changed to the actual type. Here are the types that will be included in the compiled schema: @@ -140,8 +136,8 @@ input QueryPeopleWhereWhereConditionsRelation { } ``` -Alternatively to the `columns` argument, you can also use `columnsEnum` in case you -want to re-use a list of allowed columns. Here's how your schema could look like: +Alternatively to the `columns` argument, you can also use `columnsEnum` in case you want to re-use a list of allowed columns. +Here's how your schema could look like: ```graphql type Query { @@ -167,8 +163,7 @@ Instead of creating enums for the allowed columns, it will simply use the existi It is recommended to either use the `columns` or the `columnsEnum` argument. When you don't define any allowed columns, clients can specify arbitrary column names as a `String`. -This approach should by taken with care, as it carries -potential performance and security risks and offers little type safety. +This approach should by taken with care, as it carries potential performance and security risks and offers little type safety. A simple query for a person who is exactly 42 years old would look like this: @@ -180,8 +175,7 @@ A simple query for a person who is exactly 42 years old would look like this: } ``` -Note that the operator defaults to `EQ` (`=`) if not given, so you could -also omit it from the previous example and get the same result. +Note that the operator defaults to `EQ` (`=`) if not given, so you could also omit it from the previous example and get the same result. The following query gets actors over age 37 who either have red hair or are at least 150cm: @@ -206,8 +200,8 @@ The following query gets actors over age 37 who either have red hair or are at l } ``` -Some operators require passing lists of values - or no value at all. The following -query gets people that have no hair and blue-ish eyes: +Some operators require passing lists of values - or no value at all. +The following query gets people that have no hair and blue-ish eyes: ```graphql { @@ -281,8 +275,7 @@ directive @whereHasConditions( ) on ARGUMENT_DEFINITION ``` -This directive works very similar to [@whereConditions](#whereconditions), except that -the conditions are applied to a relation sub query: +This directive works very similar to [@whereConditions](#whereconditions), except that the conditions are applied to a relation sub query: ```graphql type Query { @@ -325,8 +318,7 @@ enum QueryPeopleHasRoleColumn { } ``` -A simple query for a person who has an access level of at least 5, through one of -their roles, looks like this: +A simple query for a person who has an access level of at least 5, through one of their roles, looks like this: ```graphql { @@ -361,10 +353,10 @@ This query would retrieve all persons, no matter if they have a role or not: ## Custom operator If Lighthouse's default `SQLOperator` does not fit your use case, you can register a custom operator class. -This may be necessary if your database uses different SQL operators then Lighthouse's default, -or you want to extend/restrict the allowed operators. +This may be necessary if your database uses different SQL operators then Lighthouse's default, or you want to extend/restrict the allowed operators. -First create a class that implements `Nuwave\Lighthouse\WhereConditions\Operator`. For example: +First create a class that implements `Nuwave\Lighthouse\WhereConditions\Operator`. +For example: ```php namespace App\GraphQL; @@ -407,9 +399,8 @@ Make sure to add it after Lighthouse's service provider: ## Custom handler -If you want to take advantage of the schema generation that [@whereConditions](#whereconditions) -and [@whereHasConditions](#wherehasconditions) provide, but customize the application of arguments -to the query builder, you can provide a custom handler. +If you want to take advantage of the schema generation that [@whereConditions](#whereconditions) and [@whereHasConditions](#wherehasconditions) provide. +Customize the application of arguments to the query builder, you can provide a custom handler. ```graphql type Query { @@ -419,8 +410,7 @@ type Query { } ``` -When a client passes `where`, your handler will be called with the query builder and -the passed conditions: +When a client passes `where`, your handler will be called with the query builder and the passed conditions: ```php namespace App; diff --git a/docs/master/eloquent/getting-started.md b/docs/master/eloquent/getting-started.md index b0942e9d68..74d40974b8 100644 --- a/docs/master/eloquent/getting-started.md +++ b/docs/master/eloquent/getting-started.md @@ -26,8 +26,7 @@ type Query { } ``` -The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as -the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. +The [@all](../api-reference/directives.md#all) directive will assume the name of your model to be the same as the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field. The following query: @@ -55,8 +54,7 @@ Will return the following result: ## Pagination -You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to -query a large list of models in chunks. +You can leverage the [@paginate](../api-reference/directives.md#paginate) directive to query a large list of models in chunks. ```graphql type Query { @@ -96,8 +94,7 @@ And can be queried like this: ## Adding Query Constraints -Lighthouse provides directives such as [@eq](../api-reference/directives.md#eq) -to enhance your queries with additional constraints. +Lighthouse provides directives such as [@eq](../api-reference/directives.md#eq) to enhance your queries with additional constraints. The following field definition allows clients to find a user by their email: @@ -133,13 +130,11 @@ If found, the result will look like this: ## Ordering -Use the [@orderBy](../api-reference/directives.md#orderby) directive to sort -a result list by one or more given columns. +Use the [@orderBy](../api-reference/directives.md#orderby) directive to sort a result list by one or more given columns. ## Local Scopes -[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models -to specify reusable query constraints. +[Local scopes](https://laravel.com/docs/eloquent#local-scopes) are commonly used in Eloquent models to specify reusable query constraints. ```php use Illuminate\Database\Eloquent\Builder; @@ -154,8 +149,7 @@ final class User extends Model } ``` -Directives that query models, such as [@all](../api-reference/directives.md#all) -or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: +Directives that query models, such as [@all](../api-reference/directives.md#all) or [@first](../api-reference/directives.md#first), allow you to re-use those scopes: ```graphql type Query { @@ -215,7 +209,7 @@ type Mutation { } ``` -Since GraphQL allows you to update just parts of your data, it is best to have all arguments except `id` as optional. +Because GraphQL allows partial updates, it is best to keep all arguments optional except `id`. ```graphql mutation { @@ -251,8 +245,7 @@ To update multiple models at once, use the [@updateMany](../api-reference/direct ## Upsert -Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with -a given `id` or create it if it does not exist. +Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with a given `id` or create it if it does not exist. ```graphql type Mutation { @@ -299,7 +292,8 @@ To upsert multiple models at once, use the [@upsertMany](../api-reference/direct ## Delete -Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. Dangerously easy. +Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. +Dangerously easy. ```graphql type Mutation { @@ -317,7 +311,8 @@ mutation { } ``` -This mutation will return the deleted object, so you will have a last chance to look at the data. Use it wisely. +This mutation will return the deleted object, so you will have a last chance to look at the data. +Use it wisely. ```json { diff --git a/docs/master/eloquent/nested-mutations.md b/docs/master/eloquent/nested-mutations.md index 08659dbfc8..c3beaa8455 100644 --- a/docs/master/eloquent/nested-mutations.md +++ b/docs/master/eloquent/nested-mutations.md @@ -1,12 +1,11 @@ # Nested Mutations -Lighthouse allows you to create, update or delete models and their associated relationships, -all in one single mutation. This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). +Lighthouse allows you to create, update or delete models and their associated relationships, all in one single mutation. +This is enabled by the [nested arg resolvers mechanism](../concepts/arg-resolvers.md). ## Return Types Required -You have to define return types on your relationship methods so that Lighthouse -can detect them. +You have to define return types on your relationship methods so that Lighthouse can detect them. ```php use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -28,20 +27,17 @@ final class Post extends Model ## Partial Failure By default, all mutations are wrapped in a database transaction. -If any of the nested operations fail, the whole mutation is aborted -and no changes are written to the database. +If any of the nested operations fail, the whole mutation is aborted and no changes are written to the database. You can change this setting [in the configuration](../getting-started/configuration.md). ## Polymorphic Relation Limitations -Because the GraphQL Specification does not support polymorphic Input types (yet), -the available functionality is limited. +Because the GraphQL Specification does not support polymorphic Input types (yet), the available functionality is limited. -It is not possible to have an argument that can contain different types, which -would be necessary to pass the attributes the different related models might have. -For now, we can only support cases where the input type does not change across related -models, e.g. connecting through an ID, disconnecting or deleting the relation. +It is not possible to have an argument that can contain different types. +Would be necessary to pass the attributes the different related models might have. +For now, we can only support cases where the input type does not change across related models, e.g. connecting through an ID, disconnecting or deleting the relation. See [this issue](https://github.com/nuwave/lighthouse/issues/900) for further discussion. @@ -50,8 +46,7 @@ See [this issue](https://github.com/nuwave/lighthouse/issues/900) for further di Lighthouse has no mechanism for fine-grained permissions of nested mutation operations. Field directives such as the [@can\* family of directives](../api-reference/directives.md#can-family-of-directives) apply to the whole field. -Make sure that fields with nested mutations are only available to users who are allowed -to execute all reachable nested mutations. +Make sure that fields with nested mutations are only available to users who are allowed to execute all reachable nested mutations. ## BelongsTo @@ -63,8 +58,7 @@ type Mutation { } ``` -The mutation takes a single argument `input` that contains data about -the Post you want to create. +The mutation takes a single argument `input` that contains data about the Post you want to create. ```graphql input CreatePostInput { @@ -73,8 +67,7 @@ input CreatePostInput { } ``` -The first argument `title` is a value of the `Post` itself and corresponds -to a column in the database. +The first argument `title` is a value of the `Post` itself and corresponds to a column in the database. The second argument `author` is named just like the relationship method that is defined on the `Post` model. A nested `BelongsTo` relationship exposes the following operations: @@ -135,8 +128,7 @@ Lighthouse will create a new `Post` and associate an `User` with it. } ``` -If the related model does not exist yet, you can also -create a new one. +If the related model does not exist yet, you can also create a new one. ```graphql mutation { @@ -165,8 +157,8 @@ mutation { ``` When issuing an update, you can also allow the user to remove a relation. -Both `disconnect` and `delete` remove the association to the author, -but `delete` also removes the author model itself. +Both `disconnect` and `delete` remove the association to the author. +`delete` also removes the author model itself. ```graphql type Mutation { @@ -190,8 +182,7 @@ input UpdateUserBelongsTo { ``` You must pass a truthy value to `disconnect` and `delete` for them to actually run. -This structure was chosen as it is consistent with updating `BelongsToMany` relationships -and allows the query string to be mostly static, taking a variable value to control its behavior. +This structure was chosen as it is consistent with updating `BelongsToMany` relationships and allows the query string to be mostly static, taking a variable value to control its behavior. ```graphql mutation UpdatePost($disconnectAuthor: Boolean) { @@ -210,8 +201,8 @@ mutation UpdatePost($disconnectAuthor: Boolean) { } ``` -The `author` relationship will only be disconnected if the value of the variable -`$disconnectAuthor` is `true`, if `false` or `null` are passed, it will not change. +The `author` relationship is disconnected only when `$disconnectAuthor` is `true`. +If `false` or `null` is passed, it will not change. ```json { @@ -260,9 +251,7 @@ mutation UpdatePost($disconnectAuthor: Boolean) { ## MorphTo -The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), -the main difference being that the `connect` operation requires an input type with both -the `id` and `type` of the related model. +The basic structure of this nested mutation type is similar to [BelongsTo](#belongsto), the main difference being that the `connect` operation requires an input type with both the `id` and `type` of the related model. ```graphql type Task { @@ -367,8 +356,8 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Phone` model. +This mutation takes a single `input` argument. +It contains values of the `User` and its associated `Phone` model. ```graphql input UpdateUserInput { @@ -434,8 +423,8 @@ type Mutation { } ``` -This mutation takes a single argument `input` that contains values -of the `User` itself and its associated `Post` models. +This mutation takes a single `input` argument. +It contains values of the `User` and its associated `Post` models. ```graphql input CreateUserInput { @@ -444,8 +433,7 @@ input CreateUserInput { } ``` -Now, we can expose an operation that allows us to directly create new posts -right when we create the `User`. +Now, we can expose an operation that allows us to directly create new posts right when we create the `User`. ```graphql input CreatePostsHasMany { @@ -561,8 +549,7 @@ mutation { } ``` -The behavior for `upsert` is a mix between updating and creating, -it will produce the needed action regardless of whether the model exists or not. +The behavior for `upsert` is a mix between updating and creating, it will produce the needed action regardless of whether the model exists or not. ## MorphMany @@ -570,8 +557,7 @@ Works exactly like [Has Many](#hasmany). ## BelongsToMany -A belongs to many relation allows you to create new related models as well -as attaching existing ones. +A belongs to many relation allows you to create new related models as well as attaching existing ones. ```graphql type Mutation { @@ -648,8 +634,7 @@ Lighthouse will detect the relationship and attach, update or create it. } ``` -It is also possible to use the `sync` operation to ensure only the given IDs -will be contained within the relation. +It is also possible to use the `sync` operation to ensure only the given IDs will be contained within the relation. ```graphql mutation { @@ -680,8 +665,8 @@ input UpdateAuthorBelongsToMany { ### Storing Pivot Data It is common that many-to-many relations store some extra data in pivot tables. -Suppose we want to track what movies a user has seen. In addition to connecting -the two entities, we want to store how well they liked it: +Suppose we want to track what movies a user has seen. +In addition to connecting the two entities, we want to store how well they liked it: ```graphql type User { @@ -700,13 +685,11 @@ type UserMoviePivot { } ``` -Laravel's `sync()`, `syncWithoutDetach()` or `connect()` methods allow you to pass -an array where the keys are IDs of related models and the values are pivot data. +Laravel's `sync()`, `syncWithoutDetach()` or `connect()` methods allow you to pass an array where the keys are IDs of related models and the values are pivot data. Lighthouse exposes this capability through the nested operations on many-to-many relations. Instead of passing just a list of IDs, you can define an `input` type that also contains pivot data. -It must contain a field called `id` to contain the ID of the related model, -all other fields will be inserted into the pivot table. +It must contain a field called `id` to contain the ID of the related model, all other fields will be inserted into the pivot table. ```graphql type Mutation { diff --git a/docs/master/eloquent/polymorphic-relationships.md b/docs/master/eloquent/polymorphic-relationships.md index fc8ea0cd5b..ef5de1f768 100644 --- a/docs/master/eloquent/polymorphic-relationships.md +++ b/docs/master/eloquent/polymorphic-relationships.md @@ -27,8 +27,7 @@ type Image { ``` First, let's go ahead and add the relations to `Image` since they are straightforward. -The field name should match your relationship method name and be annotated -with the [@morphOne](../api-reference/directives.md#morphone) directive. +The field name should match your relationship method name and be annotated with the [@morphOne](../api-reference/directives.md#morphone) directive. ```graphql type Post { @@ -44,20 +43,17 @@ type User { } ``` -Depending on the rules of your application, you might require the relationship -to be there in some cases, while allowing it to be absent in others. In this -example, a `Post` must always have an `Image`, while a `User` does not require one. +Depending on the rules of your application, you might require the relationship to be there in some cases, while allowing it to be absent in others. +In this example, a `Post` must always have an `Image`, while a `User` does not require one. -For the inverse, you will need to define a [union type](../the-basics/types.md#union) -to express that an `Image` might be linked to different models. +For the inverse, you will need to define a [union type](../the-basics/types.md#union) to express that an `Image` might be linked to different models. ```graphql union Imageable = Post | User ``` Now, reference the union type from a field in your `Image` type. -You can use the [@morphTo](../api-reference/directives.md#morphto) directive -for performance optimization. +You can use the [@morphTo](../api-reference/directives.md#morphto) directive for performance optimization. ```graphql type Image { @@ -67,8 +63,8 @@ type Image { } ``` -The default type resolver will be able to determine which concrete object type is returned -when dealing with Eloquent models, so your definition should just work. +The default type resolver will be able to determine which concrete object type is returned when dealing with Eloquent models. +Your definition should just work. Given you have a field `images` that returns a list of `[Image!]!`, you could query it like this: @@ -90,10 +86,8 @@ Given you have a field `images` that returns a list of `[Image!]!`, you could qu ## One to Many -Based on the above example, you could change your application to allow -for a `Post` to have many images attached to it. -The field `images` now returns a list of `Image` object and is annotated -with the [@morphMany](../api-reference/directives.md#morphmany) directive. +Based on the above example, you could change your application to allow for a `Post` to have many images attached to it. +The field `images` now returns a list of `Image` object and is annotated with the [@morphMany](../api-reference/directives.md#morphmany) directive. ```graphql type Post { diff --git a/docs/master/eloquent/relationships.md b/docs/master/eloquent/relationships.md index ef05d66df9..5081351649 100644 --- a/docs/master/eloquent/relationships.md +++ b/docs/master/eloquent/relationships.md @@ -34,19 +34,17 @@ type Post { } ``` -Because Laravel relationships can be accessed just like regular properties on your model, -the default field resolver will work just fine. +Because Laravel relationships can be accessed just like regular properties on your model, the default field resolver will work just fine. ## Avoiding the N+1 performance problem When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. -This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: -the so-called N+1 query problem. [Learn more](../performance/n-plus-one.md). +This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: the so-called N+1 query problem. +[Learn more](../performance/n-plus-one.md). -When you decorate your relationship fields with Lighthouse's built-in relationship -directives, queries are automatically combined through a technique called _batch loading_. +When you decorate your relationship fields with Lighthouse's built-in relationship directives, queries are automatically combined through a technique called _batch loading_. That means you get fewer database requests and better performance without doing much work. > Batch loading might not provide ideal performance for all use cases. You can turn @@ -54,8 +52,7 @@ That means you get fewer database requests and better performance without doing ## One To One -Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) -between two types in your schema. +Use the [@hasOne](../api-reference/directives.md#hasone) directive to define a [one-to-one relationship](https://laravel.com/docs/eloquent-relationships#one-to-one) between two types in your schema. ```graphql type User { @@ -91,8 +88,7 @@ type Comment { ## Many To Many -While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) -are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. +While [many-to-many relationships](https://laravel.com/docs/eloquent-relationships#many-to-many) are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. Use the [@belongsToMany](../api-reference/directives.md#belongstomany) directive to define it. ```graphql @@ -131,9 +127,8 @@ type Project { ## Renaming relations -When you define a relation, Lighthouse assumes that the field and the relationship -method have the same name. If you need to name your field differently, you have to -specify the name of the method. +When you define a relation, Lighthouse assumes that the field and the relationship method have the same name. +If you need to name your field differently, you have to specify the name of the method. ```graphql type Post { diff --git a/docs/master/eloquent/soft-deleting.md b/docs/master/eloquent/soft-deleting.md index 742b23a1fb..3aa201488a 100644 --- a/docs/master/eloquent/soft-deleting.md +++ b/docs/master/eloquent/soft-deleting.md @@ -4,9 +4,7 @@ Lighthouse offers convenient helpers to work with models that use [soft deletes] ## Filter Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field -to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can add the [@softDeletes](../api-reference/directives.md#softdeletes) directive to a field to be able to query `onlyTrashed`, `withTrashed` or `withoutTrashed` elements. ```graphql type Query { @@ -14,8 +12,7 @@ type Query { } ``` -Lighthouse will automatically add an argument `trashed` to the field definition -and include the enum `Trashed`. +Lighthouse will automatically add an argument `trashed` to the field definition and include the enum `Trashed`. ```graphql type Query { @@ -44,8 +41,7 @@ You can include soft deleted models in your result with a query like this: ## Restoring Soft Deleted Models -If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, -you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. +If your model uses the `Illuminate\Database\Eloquent\SoftDeletes` trait, you can restore your model using the [@restore](../api-reference/directives.md#restore) directive. ```graphql type Mutation { @@ -67,8 +63,7 @@ This mutation will return the restored object. ## Permanently Deleting Models -To truly remove a model from the database, -use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. +To truly remove a model from the database, use the [@forceDelete](../api-reference/directives.md#forcedelete) directive. Your model must use the `Illuminate\Database\Eloquent\SoftDeletes` trait. ```graphql diff --git a/docs/master/federation/entities.md b/docs/master/federation/entities.md index fa5be6a80f..dd0da3499c 100644 --- a/docs/master/federation/entities.md +++ b/docs/master/federation/entities.md @@ -1,11 +1,9 @@ # Entities A core component of a federation capable GraphQL service is the `_entities` field. -For a given `__typename` in the given `$representations`, Lighthouse will look for -a [reference resolver](reference-resolvers.md) to return the full `_Entity`. +For a given `__typename` in the given `$representations`, Lighthouse will look for a [reference resolver](reference-resolvers.md) to return the full `_Entity`. ## Extends You have to use `@extends` in place of `extend type` to annotate type references. -This is because Lighthouse merges type extensions before the final schema is produced, -thus they would not be preserved to appear in the federation schema SDL. +This is because Lighthouse merges type extensions before the final schema is produced, thus they would not be preserved to appear in the federation schema SDL. diff --git a/docs/master/federation/entity-representations.md b/docs/master/federation/entity-representations.md index 0edf4984ae..a600a5817d 100644 --- a/docs/master/federation/entity-representations.md +++ b/docs/master/federation/entity-representations.md @@ -29,13 +29,15 @@ type Comment @extends @key(fields: "id") { ## Non-Eloquent representation If entities don't have an Eloquent relationship within the subgraph, it's necessary to specify a separate resolver that will return the required information. -The resolver should return data containing information about the `__typename` field, which corresponds to the entity's name and the primary key that can identify the entity. +The resolver should return data containing information about the `__typename` field. +This corresponds to the entity's name and the primary key that can identify the entity. The `__typename` can either be provided as an explicit field or implicitly by returning an object with a matching class name. ### Example 1 -In this example, subgraph for order service has an entity called `Order`, which in turn has an entity called `Receipt` -defined in a separate subgraph for payment service. The relationship between `Order` and `Receipt` is one-to-one. +In this example, subgraph for order service has an entity called `Order`. +In turn has an entity called `Receipt` defined in a separate subgraph for payment service. +The relationship between `Order` and `Receipt` is one-to-one. ```graphql type Order { @@ -70,8 +72,9 @@ final class Receipt ### Example 2 -In this example, subgraph for order service has an entity called `Order`, which in turn has an entity called `Product` -defined in a separate subgraph for product service. The relationship between `Order` and `Product` is one-to-many. +In this example, subgraph for order service has an entity called `Order`. +In turn has an entity called `Product` defined in a separate subgraph for product service. +The relationship between `Order` and `Product` is one-to-many. ```graphql type Order { @@ -84,7 +87,8 @@ type Product @extends @key(fields: "uuid") { } ``` -The resolver for product in order service returns an array of arrays. Each sub-array consists of: +The resolver for product in order service returns an array of arrays. +Each sub-array consists of: - `__typename` - the entity name from the product service; - `uuid` - the primary key of a specific product. diff --git a/docs/master/federation/getting-started.md b/docs/master/federation/getting-started.md index 7bdd8da33e..81df858246 100644 --- a/docs/master/federation/getting-started.md +++ b/docs/master/federation/getting-started.md @@ -10,8 +10,7 @@ It can not serve as a [federation gateway](https://www.apollographql.com/docs/fe ## Setup -Register the service provider `Nuwave\Lighthouse\Federation\FederationServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Federation\FederationServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## Publishing Your Schema @@ -48,8 +47,7 @@ extend schema ## Federated tracing -In order to use federated tracing, you need to enabled [tracing](../performance/tracing.md) -and set the driver to `Nuwave\Lighthouse\Tracing\FederatedTracing\FederatedTracing::class` in your `config/lighthouse.php`: +In order to use federated tracing, you need to enable [tracing](../performance/tracing.md) and set the driver to `Nuwave\Lighthouse\Tracing\FederatedTracing\FederatedTracing::class` in your `config/lighthouse.php`: ```php 'tracing' => [ diff --git a/docs/master/federation/reference-resolvers.md b/docs/master/federation/reference-resolvers.md index d64f34b372..c2703f0806 100644 --- a/docs/master/federation/reference-resolvers.md +++ b/docs/master/federation/reference-resolvers.md @@ -4,11 +4,9 @@ To enable the current subgraph to provide entities for other subgraphs, you need These reference resolvers act as helpers to enable cross-subgraph communication and provide data from one subgraph to another when needed. Read more about reference resolvers in the [Apollo Federation docs](https://www.apollographql.com/docs/federation/v1/entities#reference-resolvers). -Lighthouse will look for a class which name is equivalent to `__typename` in the -namespace configured in `lighthouse.federation.entities_resolver_namespace`. +Lighthouse will look for a class which name is equivalent to `__typename` in the namespace configured in `lighthouse.federation.entities_resolver_namespace`. -When you need to retrieve information from subgraphs, -the gateway automatically generates a request to the corresponding endpoint of the subgraph. +When you need to retrieve information from subgraphs, the gateway automatically generates a request to the corresponding endpoint of the subgraph. More details about this can be found in section [Query.\_entities of the Apollo Federation docs](https://www.apollographql.com/docs/federation/building-supergraphs/subgraphs-overview#query_entities). An example of such a request is shown below: @@ -25,10 +23,8 @@ An example of such a request is shown below: ## Single Entity Resolvers -After validating that type `Foo` exists, Lighthouse will look for a resolver class -in the namespace configured in `lighthouse.federation.entities_resolver_namespace`. -The resolver class is expected to contain a method `__invoke()` which takes -a single argument: the array form of the representation. +After validating that type `Foo` exists, Lighthouse will look for a resolver class in the namespace configured in `lighthouse.federation.entities_resolver_namespace`. +The resolver class is expected to contain a method `__invoke()` which takes a single argument: the array form of the representation. ```php namespace App\GraphQL\ReferenceResolvers; @@ -66,8 +62,7 @@ final class Foo ## Batched Entity Resolvers When the client requests a large number of entities with the same type, it can be more efficient to resolve them all at once. -When your entity resolver class implements `Nuwave\Lighthouse\Federation\BatchedEntityResolver`, -Lighthouse will call it a single time with an array of all representations of its type. +When your entity resolver class implements `Nuwave\Lighthouse\Federation\BatchedEntityResolver`, Lighthouse will call it a single time with an array of all representations of its type. The resolver can then do some kind of batch query to resolve them and return them all at once. ```php @@ -87,8 +82,7 @@ final class Foo implements BatchedEntityResolver } ``` -The returned iterable _must_ have the same keys as the given `array $representations` -to enable Lighthouse to return the results in the correct order. +The returned iterable _must_ have the same keys as the given `array $representations` to enable Lighthouse to return the results in the correct order. ```php namespace App\GraphQL\ReferenceResolvers; @@ -118,8 +112,7 @@ final class Product implements BatchedEntityResolver ## Eloquent Model Resolvers -When no resolver class can be found, Lighthouse will attempt to find the model that -matches the type `__typename`, using the namespaces configured in `lighthouse.namespaces.models`. +When no resolver class can be found, Lighthouse will attempt to find the model that matches the type `__typename`, using the namespaces configured in `lighthouse.namespaces.models`. ```graphql { @@ -131,8 +124,7 @@ matches the type `__typename`, using the namespaces configured in `lighthouse.na } ``` -The additional fields in the representation constrain the query builder, which is then -called and expected to return a single result. +The additional fields in the representation constrain the query builder, which is then called and expected to return a single result. In simplified terms, Lighthouse will do this: ```php @@ -149,5 +141,4 @@ return $results->first(); ``` The default model resolver makes one database query for each entity. -Therefore, for a large number of entities, it is worth considering [Batched Entity Resolvers](reference-resolvers.md#batched-entity-resolvers) -to avoid this issue. +Therefore, for a large number of entities, it is worth considering [Batched Entity Resolvers](reference-resolvers.md#batched-entity-resolvers) to avoid this issue. diff --git a/docs/master/getting-started/configuration.md b/docs/master/getting-started/configuration.md index ff948a5cac..f3bbabd076 100644 --- a/docs/master/getting-started/configuration.md +++ b/docs/master/getting-started/configuration.md @@ -11,9 +11,8 @@ The configuration file will be placed in `config/lighthouse.php`. ## CORS -A GraphQL API can be consumed from multiple clients, which may or may not reside -on the same domain as your server. Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) -for your GraphQL endpoint in `config/cors.php`: +A GraphQL API can be consumed from multiple clients, which may or may not reside on the same domain as your server. +Make sure you enable [Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors) for your GraphQL endpoint in `config/cors.php`: ```diff return [ diff --git a/docs/master/getting-started/installation.md b/docs/master/getting-started/installation.md index 1c36ca6c41..baf0c0c2e1 100644 --- a/docs/master/getting-started/installation.md +++ b/docs/master/getting-started/installation.md @@ -10,8 +10,8 @@ composer require nuwave/lighthouse ## Publish the default schema -Lighthouse includes a default schema to get you going right away. Publish -it using the following `artisan` command: +Lighthouse includes a default schema to get you going right away. +Publish it using the following `artisan` command: ```shell php artisan vendor:publish --tag=lighthouse-schema @@ -39,9 +39,8 @@ $app->register(\Nuwave\Lighthouse\LighthouseServiceProvider::class); ``` The many features Lighthouse provides are split across multiple service providers. -Since Lumen does not support auto-discovery, you will have to register them individually -depending on which features you want to use. Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), -the section `extra.laravel.providers` contains the default service providers. +Since Lumen does not support auto-discovery, you will have to register them individually depending on which features you want to use. +Check [Lighthouse's composer.json](https://github.com/nuwave/lighthouse/blob/master/composer.json), the section `extra.laravel.providers` contains the default service providers. To get you going right away in Lumen, copy over the included default schema. It uses pagination and validation, so you need to register the service providers. @@ -69,8 +68,7 @@ For Phpstorm, we recommend [the GraphQL plugin](https://plugins.jetbrains.com/pl ## Install GraphQL DevTools -To make use of the amazing tooling around GraphQL, we recommend -installing [GraphiQL](https://github.com/mll-lab/laravel-graphiql). +To make use of the amazing tooling around GraphQL, we recommend installing [GraphiQL](https://github.com/mll-lab/laravel-graphiql). ```shell composer require mll-lab/laravel-graphiql @@ -78,5 +76,5 @@ composer require mll-lab/laravel-graphiql After installation, visit `/graphiql` to try it. -You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in -the config. By default, the endpoint lives at `/graphql`. +You can use any GraphQL client with Lighthouse, make sure to point it to the URL defined in the config. +By default, the endpoint lives at `/graphql`. diff --git a/docs/master/getting-started/migrating-to-lighthouse.md b/docs/master/getting-started/migrating-to-lighthouse.md index f1e0514e0d..531660db6a 100644 --- a/docs/master/getting-started/migrating-to-lighthouse.md +++ b/docs/master/getting-started/migrating-to-lighthouse.md @@ -1,15 +1,12 @@ # Migrating to Lighthouse -This section contains advice on how you can migrate existing -API projects to Lighthouse. +This section contains advice on how you can migrate existing API projects to Lighthouse. ## Schema definition -The most important thing to get you started using Lighthouse will -be a schema that is written using GraphQL Schema Definition Language. +The most important thing to get you started using Lighthouse will be a schema that is written using GraphQL Schema Definition Language. -If you already have a server with another library up and running, you -can use introspection to retrieve this schema and save it to a file. +If you already have a server with another library up and running, you can use introspection to retrieve this schema and save it to a file. A simple tool that is also generally useful is [graphql-cli](https://github.com/graphql-cli/graphql-cli). @@ -17,23 +14,18 @@ A simple tool that is also generally useful is [graphql-cli](https://github.com/ graphql init graphql get-schema --endpoint=example.com/graphql --output=schema.graphql -Type definitions that previously done through code can mostly be deduced from -the schema. Sometimes, additional annotations or a PHP implementation is required. +Type definitions that previously done through code can mostly be deduced from the schema. +Sometimes, additional annotations or a PHP implementation is required. [How to define types](../the-basics/types.md) ## Resolver logic -If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), -[rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that -is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), -you should be able to reuse much of your existing code. +If you are coming from libraries such as [Folkloreatelier/laravel-graphql](https://github.com/Folkloreatelier/laravel-graphql), [rebing/laravel-graphql](https://github.com/rebing/graphql-laravel) or any other library that is originally based upon [webonyx/graphql-php](https://github.com/webonyx/graphql-php), you should be able to reuse much of your existing code. -You can also register your existing types within Lighthouse's type registry, so you -won't have to rewrite them in SDL: [Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). +You can also register your existing types within Lighthouse's type registry, so you won't have to rewrite them in SDL. +[Use native PHP types](../digging-deeper/adding-types-programmatically.md#native-php-types). -Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature), -so you should be able to reuse any logic you have written for Queries/Mutations. +Resolver functions share the same [common signature](../api-reference/resolvers.md#resolver-function-signature). +You should be able to reuse any logic you have written for Queries/Mutations. -Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), -[eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), -[pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). +Lighthouse simplifies many common tasks, such as [basic CRUD operations](../the-basics/fields.md), [eager loading relationships](../eloquent/relationships.md#avoiding-the-n1-performance-problem), [pagination](../api-reference/directives.md#paginate) or [validation](../security/validation.md). diff --git a/docs/master/performance/caching.md b/docs/master/performance/caching.md index 20a7656707..d0e4cda179 100644 --- a/docs/master/performance/caching.md +++ b/docs/master/performance/caching.md @@ -1,8 +1,7 @@ # Caching -If some fields in your schema are expensive or slow to compute, it can be -beneficial to cache their result. Use the [@cache](../api-reference/directives.md#cache) -directive to instruct Lighthouse to cache the result of a resolver. +If some fields in your schema are expensive or slow to compute, it can be beneficial to cache their result. +Use the [@cache](../api-reference/directives.md#cache) directive to instruct Lighthouse to cache the result of a resolver. The cache is created on the first request and is cached forever by default. Use this for values that seldom change and take long to fetch/compute. @@ -32,8 +31,7 @@ type Query { ## Clear cache -To enable this feature, you need to use a cache store that supports [cache tags](https://laravel.com/docs/cache#cache-tags) -and enable cache tags in `config/lighthouse.php`: +To enable this feature, you need to use a cache store that supports [cache tags](https://laravel.com/docs/cache#cache-tags) and enable cache tags in `config/lighthouse.php`: ```php /* @@ -47,9 +45,9 @@ and enable cache tags in `config/lighthouse.php`: 'cache_directive_tags' => true, ``` -Now, you can place the [@clearCache](../api-reference/directives.md#clearcache) directive on -mutation fields. When they are queried, they will invalidate all cache entries associated with -a calculated tag. Depending on the effect of the mutation, you can clear different tags. +Now, you can place the [@clearCache](../api-reference/directives.md#clearcache) directive on mutation fields. +When they are queried, they will invalidate all cache entries associated with a calculated tag. +Depending on the effect of the mutation, you can clear different tags. Update the cache associated with a given type without a specific ID: @@ -93,8 +91,7 @@ If your mutation affects multiple levels of cache, you can apply this directive ## Cache key When generating a cached result for a resolver, Lighthouse produces a unique key for each type. -By default, Lighthouse will look for a field of type `ID` on the parent to generate the key -for a field with [@cache](../api-reference/directives.md#cache). +By default, Lighthouse will look for a field of type `ID` on the parent to generate the key for a field with [@cache](../api-reference/directives.md#cache). This directive allows to use a different field (i.e., an external API id): @@ -107,26 +104,21 @@ type GithubProfile { ## Implementing your own cache key generator -In one of your application service providers, bind the [`Nuwave\Lighthouse\Cache\CacheKeyAndTags.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTags.php) -interface to your cache key generator class: +In one of your application service providers, bind the [`Nuwave\Lighthouse\Cache\CacheKeyAndTags.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTags.php) interface to your cache key generator class: ```php $this->app->bind(CacheKeyAndTags::class, YourOwnCacheKeyGenerator::class); ``` -You can extend [`Nuwave\Lighthouse\Cache\CacheKeyAndTagsGenerator.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTagsGenerator.php) -to override certain methods, or implement the interface from scratch. +You can extend [`Nuwave\Lighthouse\Cache\CacheKeyAndTagsGenerator.php`](https://github.com/nuwave/lighthouse/blob/master/src/Cache/CacheKeyAndTagsGenerator.php) to override certain methods, or implement the interface from scratch. ## HTTP Cache-Control header **Experimental: not enabled by default, not guaranteed to be stable.** -Register the service provider `Nuwave\Lighthouse\CacheControl\CacheControlServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\CacheControl\CacheControlServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). -You can change the [`Cache-Control` header](https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control) of your response -regardless of [@cache](../api-reference/directives.md#cache) -by adding the [@cacheControl](../api-reference/directives.md#cachecontrol) directive to a field. +You can change the [`Cache-Control` header](https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control) of your response regardless of [@cache](../api-reference/directives.md#cache) by adding the [@cacheControl](../api-reference/directives.md#cachecontrol) directive to a field. The directive can be defined on the field-level or type-level. Note that field-level settings override type-level settings. diff --git a/docs/master/performance/deferred.md b/docs/master/performance/deferred.md index 2c5aa037d4..03756561d6 100644 --- a/docs/master/performance/deferred.md +++ b/docs/master/performance/deferred.md @@ -2,22 +2,19 @@ **Experimental: not enabled by default, not guaranteed to be stable.** -Deferring fields allows you to prioritize fetching data needed to render the most important content -as fast as possible, and then loading the rest of the page in the background. +Deferring fields allows you to prioritize fetching data needed to render the most important content as fast as possible. +Then loading the rest of the page in the background. Lighthouse adds support for [the `@defer` directive](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md) through an extension. ## Setup -Register the service provider `Nuwave\Lighthouse\Defer\DeferServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Defer\DeferServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## Configuration -Consider the configuration options under `defer` in your `config/lighthouse.php` -to prevent deferred queries from running to long. +Consider the configuration options under `defer` in your `config/lighthouse.php` to prevent deferred queries from running too long.
-![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) -_(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ +![defer_example](https://user-images.githubusercontent.com/1976169/48140644-71e25500-e266-11e8-924b-08ee2f7318d1.gif) _(image from [https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e](https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e))_ diff --git a/docs/master/performance/n-plus-one.md b/docs/master/performance/n-plus-one.md index 141dc23971..b84307fa7e 100644 --- a/docs/master/performance/n-plus-one.md +++ b/docs/master/performance/n-plus-one.md @@ -1,10 +1,8 @@ # The N+1 Query Problem -A common performance pitfall that comes with the nested nature of GraphQL queries -is the so-called N+1 query problem. +A common performance pitfall that comes with the nested nature of GraphQL queries is the so-called N+1 query problem. -Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the -name of the associated author: +Let’s imagine we want to fetch a list of posts, and for each post, we want to add on the name of the associated author: ```graphql { @@ -17,19 +15,14 @@ name of the associated author: } ``` -Following a naive execution strategy, Lighthouse would first query a list of posts, -then loop over that list and resolve the individual fields. -The associated author for each post would be lazily loaded, querying the database -once per post. +Following a naive execution strategy, Lighthouse would first query a list of posts, then loop over that list and resolve the individual fields. +The associated author for each post would be lazily loaded, querying the database once per post. ## Eager Loading Relationships -When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) -is commonly used to alleviate the N+1 query problem. +When dealing with Laravel relationships, [eager loading](https://laravel.com/docs/eloquent-relationships#eager-loading) is commonly used to alleviate the N+1 query problem. -You can leverage eager loading by informing Lighthouse of the relationships between your models, -using directives such as [@belongsTo](../api-reference/directives.md#belongsto), [@hasMany](../api-reference/directives.md#hasmany) -and [@with](../api-reference/directives.md#with). +You can leverage eager loading by informing Lighthouse of the relationships between your models, using directives such as [@belongsTo](../api-reference/directives.md#belongsto), [@hasMany](../api-reference/directives.md#hasmany) and [@with](../api-reference/directives.md#with). ```graphql type Post { @@ -45,13 +38,12 @@ type User { Under the hood, Lighthouse will batch the relationship queries together in a single database query. -If you require a relation to be loaded for some field, but do not wish to return the relationship itself, -you can use the [@with](../api-reference/directives.md#with) directive. +If you require a relation to be loaded for some field. +Do not wish to return the relationship itself, you can use the [@with](../api-reference/directives.md#with) directive. ## Custom Batch Loaders -In the following example, the `User` model is associated with multiple posts, but the posts -are part of an external service. +In the following example, the `User` model is associated with multiple posts, but the posts are part of an external service. ```graphql type User { @@ -76,12 +68,11 @@ Since we have multiple users, `User.posts` would be resolved multiple times in t } ``` -We want to have a batch loader for `User.posts`, since it loads posts from a third party and the -call to fetch them is slow when run sequentially. This is assuming the posts service offers a method -to query posts for multiple users in one call. +We want to have a batch loader for `User.posts`, since it loads posts from a third party and the call to fetch them is slow when run sequentially. +This is assuming the posts service offers a method to query posts for multiple users in one call. -In order for Lighthouse to perform batch loading, it needs to group fields that are on the same level -in the query tree, but nested under different indices. When looking at the query path from `posts`, they may look like: +In order for Lighthouse to perform batch loading, it needs to group fields that are on the same level in the query tree, but nested under different indices. +When looking at the query path from `posts`, they may look like: - `users.0.posts` - `users.1.posts` @@ -107,8 +98,7 @@ function (User $user, array $args, GraphQLContext $context, ResolveInfo $resolve } ``` -The implementation of `UserPostsBatchLoader` is up to you, the only important thing is that the resolver -returns an instance of `GraphQL\Deferred`, see [webonyx/graphql-php docs](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). +The implementation of `UserPostsBatchLoader` is up to you, the only important thing is that the resolver returns an instance of `GraphQL\Deferred`, see [webonyx/graphql-php docs](https://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem). The following example illustrates some common patterns that may be found in a batch loader implementation: ```php diff --git a/docs/master/performance/query-caching.md b/docs/master/performance/query-caching.md index e3efc12ab9..d79910cafb 100644 --- a/docs/master/performance/query-caching.md +++ b/docs/master/performance/query-caching.md @@ -59,8 +59,7 @@ Other reasons to clear the query cache completely include: ## Automated Persisted Queries -Lighthouse supports Automatic Persisted Queries (APQ), compatible with the -[Apollo implementation](https://www.apollographql.com/docs/apollo-server/performance/apq). +Lighthouse supports Automatic Persisted Queries (APQ), compatible with the [Apollo implementation](https://www.apollographql.com/docs/apollo-server/performance/apq). APQ is enabled by default, but depends on query caching being enabled. diff --git a/docs/master/performance/schema-caching.md b/docs/master/performance/schema-caching.md index 41259174bf..3b8e396ad8 100644 --- a/docs/master/performance/schema-caching.md +++ b/docs/master/performance/schema-caching.md @@ -1,22 +1,19 @@ # Schema caching -As your schema grows larger, the construction of the schema from raw `.graphql` files -becomes more and more costly. +As your schema grows larger, the construction of the schema from raw `.graphql` files becomes more and more costly. Schema caching is enabled in non-local environments by default, see `config/lighthouse.php`. ## Deployment -Update your cache when deploying a new version of your application -using the [cache](../api-reference/commands.md#cache) artisan command: +Update your cache when deploying a new version of your application using the [cache](../api-reference/commands.md#cache) artisan command: ```shell php artisan lighthouse:cache ``` The structure of the serialized schema can change between Lighthouse releases. -In order to prevent errors, use a deployment method that atomically updates -both the cache file and the dependencies, e.g. K8s. +In order to prevent errors, use a deployment method that atomically updates both the cache file and the dependencies, e.g. K8s. ## Development diff --git a/docs/master/performance/server-configuration.md b/docs/master/performance/server-configuration.md index 9339ebf235..561c14b335 100644 --- a/docs/master/performance/server-configuration.md +++ b/docs/master/performance/server-configuration.md @@ -9,5 +9,4 @@ If you have the freedom to install it on your server, it's an easy way to get a ## Xdebug -Enabling Xdebug and having an active debug session slows down execution by -an order of magnitude. +Enabling Xdebug and having an active debug session slows down execution by an order of magnitude. diff --git a/docs/master/performance/tracing.md b/docs/master/performance/tracing.md index 49a431d9f8..5c9a3736ae 100644 --- a/docs/master/performance/tracing.md +++ b/docs/master/performance/tracing.md @@ -4,8 +4,7 @@ Tracing offers field-level performance monitoring for your GraphQL server. ## Setup -Register the service provider `Nuwave\Lighthouse\Tracing\TracingServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Tracing\TracingServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). ## Drivers diff --git a/docs/master/security/authentication.md b/docs/master/security/authentication.md index 8dcee6bcc2..5009fdb65c 100644 --- a/docs/master/security/authentication.md +++ b/docs/master/security/authentication.md @@ -1,16 +1,13 @@ # Authentication -You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) -to authenticate users of your GraphQL API. +You can use [standard Laravel mechanisms](https://laravel.com/docs/authentication) to authenticate users of your GraphQL API. ## AttemptAuthentication middleware -As all GraphQL requests are served at a single HTTP endpoint, middleware added -through the `lighthouse.php` config will run for all queries against your server. +As all GraphQL requests are served at a single HTTP endpoint, middleware added through the `lighthouse.php` config will run for all queries against your server. -In most cases, your schema will have some publicly accessible fields and others -that require authentication. As multiple checks for authentication or permissions may be -required in a single request, it is convenient to attempt authentication once per request. +In most cases, your schema will have some publicly accessible fields and others that require authentication. +As multiple checks for authentication or permissions may be required in a single request, it is convenient to attempt authentication once per request. ```php 'route' => [ @@ -20,12 +17,11 @@ required in a single request, it is convenient to attempt authentication once pe ], ``` -Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated -access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. +Note that the `AttemptAuthentication` middleware does _not_ protect your fields from unauthenticated access, decorate them with [@guard](../api-reference/directives.md#guard) as needed. -If you want to guard all your fields against unauthenticated access, you can simply add -Laravel's build-in auth middleware. Beware that this approach does not allow any GraphQL -operations for guest users, so you will have to handle login outside GraphQL. +If you want to guard all your fields against unauthenticated access, you can simply add Laravel's built-in auth middleware. +Beware that this approach does not allow any GraphQL operations for guest users. +So you will have to handle login outside GraphQL. ```php 'middleware' => [ @@ -41,16 +37,15 @@ You can configure default guards to use for authenticating GraphQL requests in ` 'guards' => ['api'], ``` -This setting is used whenever Lighthouse looks for an authenticated user, for example in directives -such as [@guard](../api-reference/directives.md#guard), or when applying the `AttemptAuthentication` middleware. +This setting is used whenever Lighthouse looks for an authenticated user, for example in directives such as [@guard](../api-reference/directives.md#guard). +Or when applying the `AttemptAuthentication` middleware. When multiple guards are configured, the first one that is authenticated will be used. Stateless guards are recommended for most use cases, such as the default `api` guard. ### Laravel Sanctum -If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard -to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the first middleware for Lighthouse's route. +If you are using [Laravel Sanctum](https://laravel.com/docs/sanctum) for your API, set the guard to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the first middleware for Lighthouse's route. ```php 'route' => [ @@ -64,11 +59,9 @@ to `sanctum` and register Sanctum's `EnsureFrontendRequestsAreStateful` as the f 'guards' => ['sanctum'], ``` -Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) -with all GraphQL requests, regardless of whether the user is authenticated or not. +Note that Sanctum requires you to send an CSRF token as [header](https://laravel.com/docs/csrf#csrf-x-csrf-token) with all GraphQL requests, regardless of whether the user is authenticated or not. -When using [mll-lab/laravel-graphiql](https://github.com/mll-lab/laravel-graphiql), follow the [instructions -to add a CSRF token](https://github.com/mll-lab/laravel-graphiql#configure-session-authentication). +When using [mll-lab/laravel-graphiql](https://github.com/mll-lab/laravel-graphiql), follow the [instructions to add a CSRF token](https://github.com/mll-lab/laravel-graphiql#configure-session-authentication). ## Guard selected fields @@ -80,8 +73,8 @@ type Query { } ``` -If you need to guard multiple fields, use [@guard](../api-reference/directives.md#guard) -on a `type` or an `extend type` definition. It will be applied to all fields within that type. +If you need to guard multiple fields, use [@guard](../api-reference/directives.md#guard) on a `type` or an `extend type` definition. +It will be applied to all fields within that type. ```graphql extend type Query @guard { @@ -90,8 +83,7 @@ extend type Query @guard { } ``` -The `@guard` directive will be prepended to other directives defined on the fields -and thus executes before them. +The `@guard` directive will be prepended to other directives defined on the fields and thus executes before them. ```graphql extend type Query { @@ -113,8 +105,8 @@ type Query { } ``` -Sending the following query will return the authenticated user's info -or `null` if the request is not authenticated. +Sending the following query returns the authenticated user info. +It returns `null` if the request is not authenticated. ```graphql { @@ -127,9 +119,7 @@ or `null` if the request is not authenticated. ## Stateful Authentication Example -You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). -**This only works when Lighthouse's guard uses a session driver.** -Laravel's token based authentication does not allow logging in or out on the server side. +You can create or destroy a session with mutations instead of separate API endpoints (`/login`, `/logout`). **This only works when Lighthouse's guard uses a session driver.** Laravel's token based authentication does not allow logging in or out on the server side. The implementation in the docs is only an example and may have to be adapted to your specific use case. diff --git a/docs/master/security/authorization.md b/docs/master/security/authorization.md index c9625101e7..de84df9814 100644 --- a/docs/master/security/authorization.md +++ b/docs/master/security/authorization.md @@ -3,8 +3,7 @@ Not every user in your application may be allowed to see all data or do any action. You can control what they can do by enforcing authorization rules. -Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's -a prerequisite to have your users logged in before checking what they can do. +Before you can apply authorization, make sure you cover [authentication](authentication.md) first - it's a prerequisite to have your users logged in before checking what they can do. ## Use the Viewer pattern @@ -56,8 +55,7 @@ Now, authenticated users can query for items that belong to them and are natural ## Restrict fields through policies Lighthouse allows you to restrict field operations to a certain group of users. -Use the [@can\* family of directives](../api-reference/directives.md#can-family-of-directives) -to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. +Use the [@can\* family of directives](../api-reference/directives.md#can-family-of-directives) to leverage [Laravel Policies](https://laravel.com/docs/authorization) for authorization. Starting from Laravel 5.7, [authorization of guest users](https://laravel.com/docs/authorization#guest-users) is supported. Because of this, Lighthouse does **not** validate that the user is authenticated before passing it along to the policy. @@ -87,8 +85,7 @@ final class PostPolicy ### Protect mutations using database queries -You can also protect specific models by using the [@canFind](../api-reference/directives.md#canfind) -or [@canQuery](../api-reference/directives.md#canquery) directive. +You can also protect specific models by using the [@canFind](../api-reference/directives.md#canfind) or [@canQuery](../api-reference/directives.md#canquery) directive. They will query the database and check the specified policy against the result. ```graphql @@ -186,8 +183,7 @@ final class PostPolicy } ``` -You can pass along the client given input data as arguments to the policy checks -with the `injectArgs` argument: +You can pass along the client given input data as arguments to the policy checks with the `injectArgs` argument: ```graphql type Mutation { @@ -207,8 +203,7 @@ final class PostPolicy } ``` -When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as -the second parameter and the static `args` as the third parameter: +When you combine both ways of passing arguments, the policy will be passed the `injectArgs` as the second parameter and the static `args` as the third parameter: ```php final class PostPolicy @@ -240,15 +235,12 @@ The `banned` field would return false for all users who are not authorized to ac ## Custom field restrictions -For applications with role management, it is common to hide some model attributes from a -certain group of users. At the moment, Laravel and Lighthouse offer no canonical solution -for this. +For applications with role management, it is common to hide some model attributes from a certain group of users. +At the moment, Laravel and Lighthouse offer no canonical solution for this. -A great way to implement something that fits your use case is to create -[a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). +A great way to implement something that fits your use case is to create [a custom `FieldMiddleware` directive](../custom-directives/field-directives.md#fieldmiddleware). Field middleware allows you to intercept field access and conditionally hide them. -You can hide a field by returning `null` instead of calling the final resolver, or maybe even -abort execution by throwing an error. +You can hide a field by returning `null` instead of calling the final resolver, or maybe even abort execution by throwing an error. The following directive `@canAccess` is an example implementation, make sure to adapt it to your needs. It assumes a simple role system where a `User` has a single attribute `$role`. diff --git a/docs/master/security/sanitization.md b/docs/master/security/sanitization.md index 05560796b9..5c20de2141 100644 --- a/docs/master/security/sanitization.md +++ b/docs/master/security/sanitization.md @@ -1,16 +1,14 @@ # Sanitization When dealing with user input, you need to make sure the given data is valid. -While [validation](validation) is a great first line of defense, there are cases where -it is most practical to modify the given input to ensure it is valid or safe to use. +While [validation](validation) is a great first line of defense, there are cases where it is most practical to modify the given input to ensure it is valid or safe to use. ## Single arguments A great way to deal with single values is to use an [`ArgTransformerDirective`](../custom-directives/field-argument-directives#argtransformerdirective). Lighthouse offers a few built-in options, but it is also really easy to build your own. -Here is how you can remove whitespace of a given input string by using -the built-in [@trim](../api-reference/directives.md#trim) directive: +Here is how you can remove whitespace of a given input string by using the built-in [@trim](../api-reference/directives.md#trim) directive: ```graphql type Mutation { @@ -20,6 +18,4 @@ type Mutation { ## Complex arguments -When you need to look at multiple input fields in order to run sanitization, you can use -a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) -to transform the given inputs before passing them along to the final resolver. +When you need to look at multiple input fields in order to run sanitization, you can use a [`FieldMiddlewareDirective`](../custom-directives/field-directives.md#fieldmiddleware) to transform the given inputs before passing them along to the final resolver. diff --git a/docs/master/security/validation.md b/docs/master/security/validation.md index e885b9cc8d..bbb293d5a9 100644 --- a/docs/master/security/validation.md +++ b/docs/master/security/validation.md @@ -1,12 +1,10 @@ # Validation -Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) -for your queries and mutations. +Lighthouse allows you to use [Laravel's validation](https://laravel.com/docs/validation) for your queries and mutations. ## Single Arguments -The simplest way to leverage the built-in validation rules is to use the -[@rules](../api-reference/directives.md#rules) directive. +The simplest way to leverage the built-in validation rules is to use the [@rules](../api-reference/directives.md#rules) directive. ```graphql type Mutation { @@ -14,8 +12,8 @@ type Mutation { } ``` -In the case of a validation error, Lighthouse will abort execution and return the validation messages -as part of the response. +If validation fails, Lighthouse aborts execution. +It returns the validation messages as part of the response. ```graphql mutation { @@ -96,11 +94,10 @@ input CreatePostInput { } ``` -Using the [`unique`](https://laravel.com/docs/validation#rule-unique) -validation rule can be a bit tricky. +Using the [`unique`](https://laravel.com/docs/validation#rule-unique) validation rule can be a bit tricky. -If the argument is nested within an input object, the argument path will not -match the column name, so you have to specify the column name explicitly. +If the argument is nested within an input object, the argument path will not match the column name. +So you have to specify the column name explicitly. ```graphql input CreateUserInput { @@ -110,8 +107,7 @@ input CreateUserInput { ## Validating Arrays -When you are passing in an array as an argument to a field, you might -want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) +When you are passing in an array as an argument to a field, you might want to apply some validation on the array itself, using [@rulesForArray](../api-reference/directives.md#rulesforarray) ```graphql type Mutation { @@ -122,8 +118,7 @@ type Mutation { } ``` -You can also combine this with [@rules](../api-reference/directives.md#rules) to validate -both size and contents of an argument array. +You can also combine this with [@rules](../api-reference/directives.md#rules) to validate both size and contents of an argument array. For example, you might require a list of at least 3 valid emails to be passed. ```graphql @@ -136,9 +131,9 @@ type Mutation { ## Validator Classes -In cases where your validation becomes too complex and demanding, you want to have the power of PHP to perform -complex validation. For example, accessing existing data in the database or validating the combination of input -values cannot be achieved with the examples above. This is where validator classes come into play. +In cases where your validation becomes too complex and demanding, you want to have the power of PHP to perform complex validation. +For example, accessing existing data in the database or validating the combination of input values cannot be achieved with the examples above. +This is where validator classes come into play. Validator classes can be reused on field definitions or input types within your schema. Use the [@validator](../api-reference/directives.md#validator) directive: @@ -150,15 +145,15 @@ input UpdateUserInput @validator { } ``` -We need to back that with a validator class. Lighthouse uses a simple naming convention for validator classes, -use the name of the input type and append `Validator`: +We need to back that with a validator class. +Lighthouse uses a simple naming convention for validator classes, use the name of the input type and append `Validator`: ```shell php artisan lighthouse:validator UpdateUserInputValidator ``` -The resulting class will be placed in your configured validator namespace. Let's go ahead -and define the validation rules for the input: +The resulting class will be placed in your configured validator namespace. +Let's go ahead and define the validation rules for the input: ```php namespace App\GraphQL\Validators; @@ -183,8 +178,8 @@ final class UpdateUserInputValidator extends Validator } ``` -Note that this gives you access to all kinds of programmatic validation rules that Laravel -provides. This can give you additional flexibility when you need it. +Note that this gives you access to all kinds of programmatic validation rules that Laravel provides. +This can give you additional flexibility when you need it. ### Custom Validator Messages @@ -220,13 +215,13 @@ type Mutation { } ``` -In that case, Lighthouse will look for a validator class in a sub-namespace matching the parent type, in this case -that would be `Mutation`, so the default FQCN would be `App\GraphQL\Validators\Mutation\UpdateUserValidator`. +In that case, Lighthouse will look for a validator class in a sub-namespace matching the parent type, in this case that would be `Mutation`. +The default FQCN would be `App\GraphQL\Validators\Mutation\UpdateUserValidator`. ### Validator For Nested Inputs -Use multiple validators for complex inputs that include nested input objects. This ensures -they do not grow too complex and can be composed freely. +Use multiple validators for complex inputs that include nested input objects. +This ensures they do not grow too complex and can be composed freely. ## Caveats @@ -252,8 +247,8 @@ input FooInput { } ``` -The following mutation would pass validation, because `notBar` references the `bar` field of `FooInput` -and thus its value `1` is compared to the value `2` - which is different: +The following mutation would pass validation. +`notBar` references the `bar` field of `FooInput` and thus its value `1` is compared to the value `2`, which is different: ```graphql mutation { @@ -263,8 +258,8 @@ mutation { ### Custom Rules With References -When creating custom validation rules with references, you need to tell Lighthouse -which parameters are references, so it can add the full argument path: +When creating custom validation rules with references, you need to tell Lighthouse which parameters are references. +So it can add the full argument path: ```graphql input FooInput { @@ -273,8 +268,7 @@ input FooInput { } ``` -In this example, `equal_field` is a custom rule that checks if the argument -is the same as the one referenced by the parameter. +In this example, `equal_field` is a custom rule that checks if the argument is the same as the one referenced by the parameter. The parameters to `with_reference` are: @@ -288,8 +282,7 @@ Lighthouse will call this method with the argument path leading up to the valida ### Comparisons -If you need to validate the size of an integer, you need to add the -`integer` validation rule before: +If you need to validate the size of an integer, you need to add the `integer` validation rule before: ```graphql type Mutation { @@ -298,8 +291,7 @@ type Mutation { ``` Rules that reference other fields work strictly function as such. -For example, it is not possible to use `gt` to compare against a literal value, -use `min` instead: +For example, it is not possible to use `gt` to compare against a literal value, use `min` instead: ```graphql type Mutation { @@ -315,8 +307,7 @@ type Mutation { By default, Lighthouse enables all default query validation rules from `webonyx/graphql-php`. This covers fundamental checks, e.g. queried fields match the schema, variables have values of the correct type. -If you want to add custom rules or change which ones are used, you can bind a custom implementation -of the interface `Nuwave\Lighthouse\Support\Contracts\ProvidesCacheableValidationRules` through a service provider. +If you want to add custom rules or change which ones are used, you can bind a custom implementation of the interface `Nuwave\Lighthouse\Support\Contracts\ProvidesCacheableValidationRules` through a service provider. ```php use Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules; diff --git a/docs/master/subscriptions/client-implementations.md b/docs/master/subscriptions/client-implementations.md index ec615730fc..039e8f495e 100644 --- a/docs/master/subscriptions/client-implementations.md +++ b/docs/master/subscriptions/client-implementations.md @@ -1,12 +1,10 @@ # Client Implementations -To get you up and running quickly, the following sections show how to use subscriptions -with common GraphQL client libraries. +To get you up and running quickly, the following sections show how to use subscriptions with common GraphQL client libraries. ## Apollo for Pusher -To use Lighthouse Pusher subscriptions with the [Apollo](https://www.apollographql.com/docs/react) -client library you will need to create an `apollo-link`: +To use Lighthouse Pusher subscriptions with the [Apollo](https://www.apollographql.com/docs/react) client library you will need to create an `apollo-link`: ```js import { ApolloLink, Observable } from "apollo-link"; @@ -134,8 +132,7 @@ const link = ApolloLink.from([pusherLink, httpLink(`${API_LOCATION}/graphql`)]); ## Relay Modern -To use Lighthouse's Pusher subscriptions with Relay Modern you will -need to create a custom handler and inject it into Relay's environment. +To use Lighthouse's Pusher subscriptions with Relay Modern you will need to create a custom handler and inject it into Relay's environment. ```js import Pusher from "pusher-js"; @@ -240,8 +237,7 @@ export const environment = new Environment({ ## Flutter/Dart -To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will -need to create a custom link below: +To use Lighthouse's Pusher subscriptions with Flutter/Dart GQL libraries like [Ferry](https://ferrygraphql.com), you will need to create a custom link below: ````dart import 'dart:async'; diff --git a/docs/master/subscriptions/defining-fields.md b/docs/master/subscriptions/defining-fields.md index c6ee24860a..ff15fe6ae8 100644 --- a/docs/master/subscriptions/defining-fields.md +++ b/docs/master/subscriptions/defining-fields.md @@ -17,8 +17,7 @@ php artisan lighthouse:subscription PostUpdated Lighthouse will look for a class matching the capitalized name of the field within the default subscription namespace. For example, the field `postUpdated` should have a corresponding class at `App\GraphQL\Subscriptions\PostUpdated`. -All subscription field classes **must** implement the abstract class `Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` -and implement the two methods `authorize` and `filter`. +All subscription field classes **must** implement the abstract class `Nuwave\Lighthouse\Schema\Types\GraphQLSubscription` and implement the two methods `authorize` and `filter`. ```php namespace App\GraphQL\Subscriptions; @@ -85,6 +84,4 @@ final class PostUpdated extends GraphQLSubscription } ``` -If the default namespaces are not working with your application structure -or you want to be more explicit, you can use the [@subscription](../api-reference/directives.md#subscription) -directive to point to a different class. +If the default namespaces are not working with your application structure or you want to be more explicit, you can use the [@subscription](../api-reference/directives.md#subscription) directive to point to a different class. diff --git a/docs/master/subscriptions/filtering-subscriptions.md b/docs/master/subscriptions/filtering-subscriptions.md index c4101ac0c6..3c6d132093 100644 --- a/docs/master/subscriptions/filtering-subscriptions.md +++ b/docs/master/subscriptions/filtering-subscriptions.md @@ -1,6 +1,8 @@ # Filtering Subscriptions -There are times when you'll need to filter out specific events based on the arguments provided by the client. To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. For instance, using the following example: +There are times when you'll need to filter out specific events based on the arguments provided by the client. +To handle this, you can return a true/false from the `filter` function to indicate whether the client should receive the subscription. +For instance, using the following example: ```graphql subscription onPostUpdated($post_id: ID!) { diff --git a/docs/master/subscriptions/getting-started.md b/docs/master/subscriptions/getting-started.md index 21d20fcbd6..4e26b0f3d3 100644 --- a/docs/master/subscriptions/getting-started.md +++ b/docs/master/subscriptions/getting-started.md @@ -1,27 +1,20 @@ # Subscriptions: Getting Started -Subscriptions allow GraphQL clients to observe specific events -and receive updates from the server when those events occur. +Subscriptions allow GraphQL clients to observe specific events and receive updates from the server when those events occur. -::: tip NOTE -Much of the credit should be given to the [Ruby implementation](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/overview.md) as they provided a great overview of how the backend should work. -::: +::: tip NOTE Much of the credit should be given to the [Ruby implementation](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/overview.md) as they provided a great overview of how the backend should work. ::: ## Setup -Register the service provider `Nuwave\Lighthouse\Subscriptions\SubscriptionServiceProvider`, -see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). +Register the service provider `Nuwave\Lighthouse\Subscriptions\SubscriptionServiceProvider`, see [registering providers in Laravel](https://laravel.com/docs/providers#registering-providers). -If you want to use [the Pusher driver](https://laravel.com/docs/11.x/broadcasting#pusher-channels), you need to install the [Pusher PHP Library](https://github.com/pusher/pusher-http-php) -for interacting with the Pusher HTTP API. +If you want to use [the Pusher driver](https://laravel.com/docs/11.x/broadcasting#pusher-channels), you need to install the [Pusher PHP Library](https://github.com/pusher/pusher-http-php) for interacting with the Pusher HTTP API. composer require pusher/pusher-php-server -If you want to use [the Laravel Echo driver](https://laravel.com/docs/broadcasting#client-side-installation), -you need to set the env `LIGHTHOUSE_BROADCASTER=echo`. +If you want to use [the Laravel Echo driver](https://laravel.com/docs/broadcasting#client-side-installation), you need to set the env `LIGHTHOUSE_BROADCASTER=echo`. -When using subscriptions with [Laravel Octane](https://laravel.com/docs/octane), -add the following to your `config/octane.php`: +When using subscriptions with [Laravel Octane](https://laravel.com/docs/octane), add the following to your `config/octane.php`: ```php 'warm' => [ @@ -33,17 +26,17 @@ add the following to your `config/octane.php`: ### Empty Response Optimization Lighthouse returns the subscription channel as part of the response under `extensions`. -If `subscriptions.exclude_empty` in `lighthouse.php` is set to `true`, -API responses without a subscription channel will not contain `lighthouse_subscriptions` in `extensions`. -This optimizes performance by sending less data, but clients must anticipate this appropriately. +If `subscriptions.exclude_empty` in `lighthouse.php` is set to `true`, API responses without a subscription channel will not contain `lighthouse_subscriptions` in `extensions`. +This optimizes performance by sending less data, +but clients must anticipate this appropriately. ## Expiring Subscriptions Subscriptions do not expire by themselves. Unless you delete a subscription, it will continue to broadcast events after the client has disconnected. -The easiest way to expire subscriptions automatically is to use the env `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL` -to set an expiration time in seconds (e.g. `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL=3600` to expire in one hour). +The easiest way to expire subscriptions automatically is to use the env `LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL` to set an expiration time in seconds (e.g. +`LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL=3600` to expire in one hour). ## Encrypted Subscriptions @@ -76,4 +69,5 @@ The webhook URL will typically be: /graphql/subscriptions/webhook ``` -You can add the webhook in the Pusher Dashboard. Select the type `channel existence`. +You can add the webhook in the Pusher Dashboard. +Select the type `channel existence`. diff --git a/docs/master/subscriptions/trigger-subscriptions.md b/docs/master/subscriptions/trigger-subscriptions.md index 8c283056b2..33307b4422 100644 --- a/docs/master/subscriptions/trigger-subscriptions.md +++ b/docs/master/subscriptions/trigger-subscriptions.md @@ -1,12 +1,10 @@ # Trigger Subscriptions -Now that clients can subscribe to a field, you will need to notify Lighthouse -when the underlying data has changed. +Now that clients can subscribe to a field, you will need to notify Lighthouse when the underlying data has changed. ## Broadcast Directive -The [@broadcast](../api-reference/directives.md#broadcast) -directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. +The [@broadcast](../api-reference/directives.md#broadcast) directive will broadcast all updates to the `Post` model to the `postUpdated` subscription. ```graphql type Mutation { @@ -15,13 +13,11 @@ type Mutation { } ``` -You can reference the same subscription from multiple fields, or vice-versa -trigger multiple subscriptions from a single field. +You can reference the same subscription from multiple fields, or vice-versa trigger multiple subscriptions from a single field. ## Fire Subscriptions From Code -The `Subscription` class offers a utility method `broadcast` -that can be used to broadcast subscriptions from anywhere in your application. +The `Subscription` class offers a utility method `broadcast` that can be used to broadcast subscriptions from anywhere in your application. It accepts three parameters: @@ -29,8 +25,7 @@ It accepts three parameters: - `mixed $root` The result object you want to pass through - `bool $shouldQueue = null` Optional, overrides the default configuration `lighthouse.subscriptions.queue_broadcasts` -The following example shows how to trigger a subscription after an update -to the `Post` model. +The following example shows how to trigger a subscription after an update to the `Post` model. ```php $post->title = $newTitle; diff --git a/docs/master/testing/extensions.md b/docs/master/testing/extensions.md index e90a00ced7..326d257487 100644 --- a/docs/master/testing/extensions.md +++ b/docs/master/testing/extensions.md @@ -1,12 +1,10 @@ # Testing Lighthouse extensions -When you extend Lighthouse with custom functionality, it is a great idea to test -your extensions in isolation from the rest of your application. +When you extend Lighthouse with custom functionality, it is a great idea to test your extensions in isolation from the rest of your application. ## Use a test schema -When you enhance functionality related to the schema definition, such as adding -a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. +When you enhance functionality related to the schema definition, such as adding a [custom directive](../custom-directives/getting-started.md), you need a test schema where you can use it. Add the `UsesTestSchema` trait to your base test class, call `setUpTestSchema()` and define your test schema: ```php @@ -40,8 +38,8 @@ final class MyCustomDirectiveTest extends TestCase ## Mock resolvers -When testing custom functionality through a dummy schema, you still need to have -a way to resolve fields. Lighthouse provides a simple way to mock resolvers in a dummy schema. +When testing custom functionality through a dummy schema, you still need to have a way to resolve fields. +Lighthouse provides a simple way to mock resolvers in a dummy schema. Add the `MocksResolvers` trait to your test class: @@ -90,9 +88,9 @@ public function testReverseField(): void } ``` -Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert -that our resolver is called with certain values. Note that we are not passing an -explicit resolver function here. The default resolver will simply return `null`. +Since we get back an instance of PHPUnit's `InvocationMocker`, we can also assert that our resolver is called with certain values. +Note that we are not passing an explicit resolver function here. +The default resolver will simply return `null`. ```php public function testReverseInput(): void @@ -118,8 +116,7 @@ public function testReverseInput(): void } ``` -If you have to handle the incoming resolver arguments dynamically, you can also -pass a function that is called: +If you have to handle the incoming resolver arguments dynamically, you can also pass a function that is called: ```php public function testReverseInput(): void @@ -146,8 +143,8 @@ public function testReverseInput(): void } ``` -You might have a need to add multiple resolvers to a single schema. For that case, -specify a unique `key` for the mock resolver (it defaults to `default`): +You might have a need to add multiple resolvers to a single schema. +For that case, specify a unique `key` for the mock resolver (it defaults to `default`): ```php public function testMultipleResolvers(): void diff --git a/docs/master/testing/phpunit.md b/docs/master/testing/phpunit.md index c2b92b1656..f000307606 100644 --- a/docs/master/testing/phpunit.md +++ b/docs/master/testing/phpunit.md @@ -104,11 +104,9 @@ public function testPostsSubscription(): void ## Assertions -Now that we know how to query our server in tests, we need to make sure the -returned results match our expectations. +Now that we know how to query our server in tests, we need to make sure the returned results match our expectations. -The returned `TestResponse` conveniently offers assertions that work quite -well with the JSON data returned by GraphQL. +The returned `TestResponse` conveniently offers assertions that work quite well with the JSON data returned by GraphQL. The `assertJson` method asserts that the response is a superset of the given JSON. @@ -253,12 +251,9 @@ $this ## Testing Errors -Depending on your debug and error handling configuration, Lighthouse catches most if -not all errors produced within queries and includes them within the result. +Depending on your debug and error handling configuration, Lighthouse catches most if not all errors produced within queries and includes them within the result. -One way to test for errors is to examine the `TestResponse`, either by looking -at the JSON response manually or by using the provided [assertion mixins](#testresponse-assertion-mixins) -such as `assertGraphQLErrorMessage()`: +One way to test for errors is to examine the `TestResponse`, either by looking at the JSON response manually or by using the provided [assertion mixins](#testresponse-assertion-mixins) such as `assertGraphQLErrorMessage()`: ```php $this @@ -315,8 +310,8 @@ $this->multipartGraphQL($operations, $map, $file); ## Introspection -If you create or manipulate parts of your schema programmatically, you might -want to test that. You can use introspection to query your final schema in tests. +If you create or manipulate parts of your schema programmatically, you might want to test that. +You can use introspection to query your final schema in tests. Lighthouse uses the introspection query from [`GraphQL\Type\Introspection::getIntrospectionQuery()`](https://github.com/webonyx/graphql-php/blob/master/src/Type/Introspection.php). @@ -382,8 +377,7 @@ $this->setUpDeferStream(); ## Lumen -Because the `TestResponse` class is not available in Lumen, you must use a different -test trait: +Because the `TestResponse` class is not available in Lumen, you must use a different test trait: ```diff ` -and including it in your schema. Lighthouse will look for Scalar types in a configurable -default namespace. +Define your own scalar types with `php artisan lighthouse:scalar `. +Then include them in your schema. +Lighthouse will look for Scalar types in a configurable default namespace. ```graphql scalar ZipCode @@ -85,8 +84,8 @@ type Query { } ``` -In this example, the underlying values are actually integers. When the models are retrieved from -the database, the mapping is applied and the integers are converted to the defined string keys. +In this example, the underlying values are actually integers. +When the models are retrieved from the database, the mapping is applied and the integers are converted to the defined string keys. ```php return [ @@ -131,8 +130,7 @@ The PHP internal value of the field `ADMIN` will be `string('ADMIN')`. ### Native PHP definition -If you want to reuse enum definitions from PHP, you can [construct a `PhpEnumType`](https://webonyx.github.io/graphql-php/type-definitions/enums/#construction-from-php-enum) -and [register it through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types): +If you want to reuse enum definitions from PHP, you can [construct a `PhpEnumType`](https://webonyx.github.io/graphql-php/type-definitions/enums/#construction-from-php-enum) and [register it through the TypeRegistry](../digging-deeper/adding-types-programmatically.md#native-php-types): ```php use GraphQL\Type\Definition\Deprecated; @@ -158,8 +156,7 @@ $typeRegistry->register(new PhpEnumType(Fruit::class)); ### bensampo/laravel-enum -If you are using [bensampo/laravel-enum](https://github.com/BenSampo/laravel-enum) -you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. +If you are using [bensampo/laravel-enum](https://github.com/BenSampo/laravel-enum) you can use `Nuwave\Lighthouse\Schema\Types\LaravelEnumType` to construct an enum type from it. ```php use BenSampo\Enum\Enum; @@ -254,8 +251,7 @@ enum Color { ## Input Input types can be used to describe complex objects for field arguments. -Beware that while they look similar to Object Types, they behave differently: -The fields of an Input Type are treated similar to arguments. +Beware that while they look similar to Object Types, they behave differently: The fields of an Input Type are treated similar to arguments. ```graphql input CreateUserInput { @@ -303,20 +299,21 @@ type User implements Named { } ``` -Interfaces need a way of determining which concrete Object Type is returned by a -particular query. Lighthouse provides a default type resolver that works by calling -`class_basename($value)` on the value returned by the resolver. +Interfaces need a way of determining which concrete Object Type is returned by a particular query. +Lighthouse provides a default type resolver. +It calls `class_basename()` on the resolved value. -You can also provide a custom type resolver. Run `php artisan lighthouse:interface ` to create -a custom interface class. It is automatically put in the default namespace where Lighthouse can discover it by itself. +You can also provide a custom type resolver. +Run `php artisan lighthouse:interface ` to create a custom interface class. +It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#interfaces) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/interfaces) ## Union A Union is an abstract type that simply enumerates other Object Types. -They are similar to interfaces in that they can return different types, but do not prescribe any common fields. +They are similar to interfaces in that they can return different types. +But do not prescribe any common fields. ```graphql union Person = User | Employee @@ -333,8 +330,7 @@ type Employee { ``` Just like Interfaces, you need a way to determine the concrete Object Type for a Union, based on the resolved value. -If the default type resolver does not work for you, define your own using `php artisan lighthouse:union `. +If the default type resolver does not work for you, define your own with `php artisan lighthouse:union `. It is automatically put in the default namespace where Lighthouse can discover it by itself. -Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the -[docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) +Read more about them in the [GraphQL Reference](https://graphql.org/learn/schema/#union-types) and the [docs for graphql-php](https://webonyx.github.io/graphql-php/type-definitions/unions) diff --git a/docs/tutorial/README.md b/docs/tutorial/README.md index 6de5464347..e69edcec76 100644 --- a/docs/tutorial/README.md +++ b/docs/tutorial/README.md @@ -5,8 +5,7 @@ sidebar: auto # Tutorial This is an introductory tutorial for building a GraphQL server with Lighthouse. -While we try to keep it beginner-friendly, we recommend familiarizing yourself -with [GraphQL](https://graphql.org) and [Laravel](https://laravel.com) first. +While we try to keep it beginner-friendly, we recommend familiarizing yourself with [GraphQL](https://graphql.org) and [Laravel](https://laravel.com) first. The source code of the finished project is available at [nuwave/lighthouse-tutorial](https://github.com/nuwave/lighthouse-tutorial). @@ -14,24 +13,21 @@ The source code of the finished project is available at [nuwave/lighthouse-tutor GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. -GraphQL provides a complete and understandable description of the data in your API, -gives clients the power to ask for exactly what they need and nothing more, -makes it easier to evolve APIs over time, and enables powerful developer tools. +GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time. +Enables powerful developer tools.
Screenshot of GraphiQL with Doc Explorer Open - GraphiQL +GraphiQL
GraphQL has been released only as a [_specification_](https://facebook.github.io/graphql). -This means that GraphQL is in fact not more than a long document that describes in detail -the behavior of a GraphQL server. +This means that GraphQL is in fact not more than a long document that describes in detail the behavior of a GraphQL server. GraphQL has its own type system that’s used to define the schema of an API. The syntax for writing schemas is called [Schema Definition Language](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51) or short **SDL**. -Here is an example how we can use the SDL to define a type called `User` and its -relation to another type `Post`. +Here is an example how we can use the SDL to define a type called `User` and its relation to another type `Post`. ```graphql type User { @@ -63,7 +59,7 @@ The process of building a GraphQL server with Lighthouse can be described in 3 s
- The role of GraphQL in your application +The role of GraphQL in your application
## Agenda @@ -74,24 +70,19 @@ In this tutorial we will create a GraphQL API for a simple Blog from scratch wit - Lighthouse - GraphiQL -::: tip -You can download the source code for this tutorial at [https://github.com/nuwave/lighthouse-tutorial](https://github.com/nuwave/lighthouse-tutorial) -::: +::: tip You can download the source code for this tutorial at [https://github.com/nuwave/lighthouse-tutorial](https://github.com/nuwave/lighthouse-tutorial) ::: ## Installation ### Create a new Laravel project -::: tip -This tutorial starts with a fresh Laravel project. -You can use an existing project and skip ahead to [Installing Lighthouse](#installing-lighthouse), -but you may have to adapt a few things to fit your existing app as we go along. -::: +::: tip This tutorial starts with a fresh Laravel project. +You can use an existing project and skip ahead to [Installing Lighthouse](#installing-lighthouse). +You may have to adapt a few things to fit your existing app as we go along. ::: Create a new project by following [installing Laravel](https://laravel.com/docs/#installing-laravel). -Consult the [Laravel docs on database configuration](https://laravel.com/docs/database#configuration) -and ensure you have a working database set up. +Consult the [Laravel docs on database configuration](https://laravel.com/docs/database#configuration) and ensure you have a working database set up. Run database migrations to create the `users` table: @@ -120,8 +111,7 @@ Publish the default schema to `graphql/schema.graphql`: php artisan vendor:publish --tag=lighthouse-schema ``` -We will use [GraphiQL](https://github.com/graphql/graphiql/tree/main/packages/graphiql) -to interactively run GraphQL queries: +We will use [GraphiQL](https://github.com/graphql/graphiql/tree/main/packages/graphiql) to interactively run GraphQL queries: ```shell composer require mll-lab/laravel-graphiql @@ -141,8 +131,7 @@ To make sure everything is working, access `/graphiql` and try this query: ## The Models -This first part will show you how to set up the models and database migrations -and does not include any specifics related to GraphQL or Lighthouse. +This first part will show you how to set up the models and database migrations and does not include any specifics related to GraphQL or Lighthouse. Our blog follows some simples rules: @@ -153,7 +142,7 @@ We can model this in our database schema like this.
-

Database relations diagram

+

Database relations diagram

Begin by defining models and migrations for your posts and comments @@ -313,8 +302,7 @@ final class User extends Authenticatable ## The Schema -Let's edit `graphql/schema.graphql` and define our blog schema, -based on the Eloquent models we created. +Let's edit `graphql/schema.graphql` and define our blog schema, based on the Eloquent models we created. We add two queries for retrieving posts to the root `Query` type: @@ -326,12 +314,11 @@ type Query { } ``` -The way that Lighthouse knows how to resolve the queries is a combination of convention-based -naming - the type name `Post` is also the name of our Model - and the use of server-side directives. +The way that Lighthouse knows how to resolve the queries is a combination of convention-based naming - the type name `Post` is also the name of our Model - and the use of server-side directives. - [@all](../master/api-reference/directives.md#all) returns a list of all `Post` models - [@find](../master/api-reference/directives.md#find) and [@eq](../master/api-reference/directives.md#eq) - are combined to retrieve a single `Post` by its ID +are combined to retrieve a single `Post` by its ID We add additional type definitions that clearly define the shape of our data: @@ -360,13 +347,11 @@ type Comment { } ``` -Just like in Eloquent, we express the relationship between our types using the -[@belongsTo](../master/api-reference/directives.md#belongsto) and [@hasMany](../master/api-reference/directives.md#hasmany) directives. +Just like in Eloquent, we express the relationship between our types using the [@belongsTo](../master/api-reference/directives.md#belongsto) and [@hasMany](../master/api-reference/directives.md#hasmany) directives. ## The Result -Insert some fake data into your database, -you can use [Laravel seeders](https://laravel.com/docs/seeding) for that. +Insert some fake data into your database, you can use [Laravel seeders](https://laravel.com/docs/seeding) for that. Visit `/graphiql` and try the following query: diff --git a/src/Auth/BaseCanDirective.php b/src/Auth/BaseCanDirective.php index e411b78ebd..f1d463c786 100644 --- a/src/Auth/BaseCanDirective.php +++ b/src/Auth/BaseCanDirective.php @@ -127,8 +127,10 @@ public function handleField(FieldValue $fieldValue): void * Authorizes request and optionally resolves the field. * * This method is called inside the authorization try-catch block. - * Resolving the field here is optional, it will be done outside the try-catch block if not resolved here. - * Resolving inside this method means any exceptions thrown by the resolver will be caught and handled according to the `action` argument. + * Resolving the field here is optional. + * It will be done outside the try-catch block if this method does not resolve it. + * Resolving inside this method means any exceptions thrown by the resolver are caught. + * Those exceptions are handled according to the `action` argument. * * @phpstan-import-type Resolver from \Nuwave\Lighthouse\Schema\Values\FieldValue as Resolver * diff --git a/src/Bind/ModelBinding.php b/src/Bind/ModelBinding.php index a5987a2310..af6adfb58f 100644 --- a/src/Bind/ModelBinding.php +++ b/src/Bind/ModelBinding.php @@ -45,8 +45,8 @@ protected function modelInstance(EloquentCollection $results): ?Model } /** - * Binding collections should be returned with the original values - * as keys to allow validating the binding when required. + * Binding collections should be returned with the original values as keys. + * This allows validating the binding when required. * * @see \Nuwave\Lighthouse\Bind\BindDirective::rules() * diff --git a/src/Bind/Validation/BindingExists.php b/src/Bind/Validation/BindingExists.php index 2c6c0c20bb..3d545a61e6 100644 --- a/src/Bind/Validation/BindingExists.php +++ b/src/Bind/Validation/BindingExists.php @@ -16,8 +16,8 @@ public function __construct( ) {} /** - * Because of backwards compatibility with Laravel 9, typehints for this method - * must be set through PHPDoc as the interface did not include typehints. + * Because of backwards compatibility with Laravel 9, this method sets typehints through PHPDoc. + * The interface did not include typehints. * * @see https://laravel.com/docs/9.x/validation#using-rule-objects * @@ -51,8 +51,8 @@ public function __invoke($attribute, $value, $fail): void } /** - * Because of backwards compatibility with Laravel 9, typehints for this method - * must be set through PHPDoc as the interface did not include typehints. + * Because of backwards compatibility with Laravel 9, this method sets typehints through PHPDoc. + * The interface did not include typehints. * * @see https://laravel.com/docs/9.x/validation#custom-validation-rules * diff --git a/src/ClientDirectives/ClientDirective.php b/src/ClientDirectives/ClientDirective.php index f667551621..39df695488 100644 --- a/src/ClientDirectives/ClientDirective.php +++ b/src/ClientDirectives/ClientDirective.php @@ -10,8 +10,8 @@ use Nuwave\Lighthouse\Schema\SchemaBuilder; /** - * Provides information about where client directives - * were placed in the query and what arguments were given to them. + * Provides information about where client directives were placed in the query. + * It also provides the arguments given to them. * * TODO implement accessors for other locations https://spec.graphql.org/draft/#ExecutableDirectiveLocation */ @@ -27,8 +27,8 @@ public function __construct( * Get the given values for a client directive. * * This returns an array of the given arguments for all field nodes. - * The number of items in the returned result will always be equivalent - * to the number of field nodes, each having one of the following values: + * The number of items in the returned result is always equivalent to the number of field nodes. + * Each entry has one of the following values: * - When a field node does not have the directive on it: null * - When the directive is present but has no arguments: [] * - When the directive is present with arguments: an associative array diff --git a/src/Console/IdeHelperCommand.php b/src/Console/IdeHelperCommand.php index c83b195fc6..65ba8ecf3e 100644 --- a/src/Console/IdeHelperCommand.php +++ b/src/Console/IdeHelperCommand.php @@ -151,8 +151,9 @@ public static function schemaDirectivesPath(): string /** * Users may register types programmatically, e.g. in service providers. - * In order to allow referencing those in the schema, it is useful to print - * those types to a helper schema, excluding types the user defined in the schema. + * It is useful to print those types to a helper schema. + * This allows referencing them in the schema. + * This excludes types the user defined in the schema. */ public function programmaticTypes(SchemaSourceProvider $schemaSourceProvider, ASTCache $astCache, SchemaBuilder $schemaBuilder): void { diff --git a/src/Console/LighthouseGeneratorCommand.php b/src/Console/LighthouseGeneratorCommand.php index a66611ec8f..b4b077fa00 100644 --- a/src/Console/LighthouseGeneratorCommand.php +++ b/src/Console/LighthouseGeneratorCommand.php @@ -9,9 +9,10 @@ abstract class LighthouseGeneratorCommand extends GeneratorCommand /** * Get the desired class name from the input. * - * As a typical workflow would be to write the schema first and then copy-paste - * a field name to generate a class for it, we uppercase it so the user does - * not run into unnecessary errors. You're welcome. + * A typical workflow is to write the schema first and then copy-paste a field name. + * This command generates a class for that field. + * We uppercase it so the user does not run into unnecessary errors. + * You're welcome. */ protected function getNameInput(): string { diff --git a/src/Events/EndRequest.php b/src/Events/EndRequest.php index bc049d68a4..90504993b5 100644 --- a/src/Events/EndRequest.php +++ b/src/Events/EndRequest.php @@ -8,8 +8,7 @@ /** * Fires right after building the HTTP response in the GraphQLController. * - * Can be used for logging or for measuring and monitoring - * the time a request takes to resolve. + * Can be used for logging or for measuring and monitoring the time a request takes to resolve. * * @see \Nuwave\Lighthouse\Http\GraphQLController */ diff --git a/src/Events/ManipulateResult.php b/src/Events/ManipulateResult.php index 6e4d2d0fc3..068c4d412f 100644 --- a/src/Events/ManipulateResult.php +++ b/src/Events/ManipulateResult.php @@ -7,8 +7,8 @@ /** * Fires after resolving each individual query. * - * This gives listeners an easy way to manipulate the query - * result without worrying about batched execution. + * This gives listeners an easy way to manipulate the query result. + * It avoids worrying about batched execution. */ class ManipulateResult { diff --git a/src/Events/StartRequest.php b/src/Events/StartRequest.php index 373e759a0a..0128bdab26 100644 --- a/src/Events/StartRequest.php +++ b/src/Events/StartRequest.php @@ -8,8 +8,7 @@ /** * Fires right after a request reaches the GraphQLController. * - * Can be used for logging or for measuring and monitoring - * the time a request takes to resolve. + * Can be used for logging or for measuring and monitoring the time a request takes to resolve. * * @see \Nuwave\Lighthouse\Http\GraphQLController */ diff --git a/src/Execution/Arguments/ArgPartitioner.php b/src/Execution/Arguments/ArgPartitioner.php index 606c247c95..5fc82bb892 100644 --- a/src/Execution/Arguments/ArgPartitioner.php +++ b/src/Execution/Arguments/ArgPartitioner.php @@ -47,8 +47,7 @@ public static function nestedArgResolvers(ArgumentSet $argumentSet, mixed $root) * ['foo' => 'Bar'], * ] * - * and the model has a method "comments" that returns a HasMany relationship, - * the result will be: + * and the model has a method "comments" that returns a HasMany relationship, the result will be: * [ * [ * 'comments' => @@ -133,8 +132,8 @@ protected static function attachNestedArgResolver(string $name, Argument &$argum /** * Partition arguments based on a predicate. * - * The predicate will be called for each argument within the ArgumentSet - * with the following parameters: + * The predicate is called for each argument within the ArgumentSet. + * It receives the following parameters: * 1. The name of the argument * 2. The argument itself * diff --git a/src/Execution/Arguments/NestedManyToMany.php b/src/Execution/Arguments/NestedManyToMany.php index a2ac78e90b..68f2f08d3b 100644 --- a/src/Execution/Arguments/NestedManyToMany.php +++ b/src/Execution/Arguments/NestedManyToMany.php @@ -83,9 +83,8 @@ public function __invoke($model, $args): void /** * Generate an array for passing into sync, syncWithoutDetaching or connect method. * - * Those functions natively have the capability of passing additional - * data to store in the pivot table. That array expects passing the id's - * as keys, so we transform the passed arguments to match that. + * Those functions can natively pass additional data for storage in the pivot table. + * That array expects passing the IDs as keys, so we transform the passed arguments to match that. * * @return array */ diff --git a/src/Execution/BatchLoader/BatchLoaderRegistry.php b/src/Execution/BatchLoader/BatchLoaderRegistry.php index e0436018a8..d67c1b1d7f 100644 --- a/src/Execution/BatchLoader/BatchLoaderRegistry.php +++ b/src/Execution/BatchLoader/BatchLoaderRegistry.php @@ -35,8 +35,8 @@ public static function instance(array $pathToField, callable $makeInstance): obj /** * Remove all stored BatchLoaders. * - * This is called after Lighthouse has resolved a query, so multiple - * queries can be handled in a single request/session. + * This is called after Lighthouse has resolved a query. + * It allows handling multiple queries in a single request/session. */ public static function forgetInstances(): void { diff --git a/src/Execution/Utils/ModelKey.php b/src/Execution/Utils/ModelKey.php index 0d10ffcdfc..b8da3d30a3 100644 --- a/src/Execution/Utils/ModelKey.php +++ b/src/Execution/Utils/ModelKey.php @@ -5,8 +5,7 @@ use Illuminate\Database\Eloquent\Model; /** - * Create a model key that concatenates the models fully-qualified class - * name and key or composite key. + * Create a model key that concatenates the models fully-qualified class name and key or composite key. */ class ModelKey { diff --git a/src/Federation/Resolvers/Entities.php b/src/Federation/Resolvers/Entities.php index d759b20835..cd50398d9a 100644 --- a/src/Federation/Resolvers/Entities.php +++ b/src/Federation/Resolvers/Entities.php @@ -39,7 +39,8 @@ public function __invoke(mixed $root, array $args, GraphQLContext $context, Reso }; /** - * Firstly, representations are grouped by typename to allow assigning the correct resolver for each entity. + * First, representations are grouped by typename. + * That allows assigning the correct resolver for each entity. * Secondly, they are deduplicated based on their hash to avoid resolving the same entity twice. * * @var array>> $groupedRepresentations diff --git a/src/GlobalId/Base64GlobalId.php b/src/GlobalId/Base64GlobalId.php index 0e1b43470b..71837e8e3f 100644 --- a/src/GlobalId/Base64GlobalId.php +++ b/src/GlobalId/Base64GlobalId.php @@ -11,8 +11,8 @@ * 2. Glue them together, separated by a colon, e.g. "User:123" * 3. base64_encode the result * - * This can then be reversed to uniquely identify an entity in our schema, - * just by looking at a single ID. + * This can then be reversed to uniquely identify an entity in our schema. + * A single ID is enough. */ class Base64GlobalId implements GlobalId { diff --git a/src/GlobalId/NodeRegistry.php b/src/GlobalId/NodeRegistry.php index 5665d9c560..d986f785d0 100644 --- a/src/GlobalId/NodeRegistry.php +++ b/src/GlobalId/NodeRegistry.php @@ -23,9 +23,9 @@ class NodeRegistry /** * The stashed current type. * - * Since PHP resolves the fields synchronously and one after another, - * we can safely stash just this one value. Should the need arise, this - * can probably be a map from the unique field path to the type. + * PHP resolves fields synchronously and one after another. + * So we can safely stash just this one value. + * Should the need arise, this can probably be a map from the unique field path to the type. */ protected string $currentType; diff --git a/src/Http/Middleware/AcceptJson.php b/src/Http/Middleware/AcceptJson.php index d96edc7005..c7c58db8da 100644 --- a/src/Http/Middleware/AcceptJson.php +++ b/src/Http/Middleware/AcceptJson.php @@ -7,9 +7,8 @@ /** * Always set the `Accept: application/json` header. * - * This makes it easier to do simple GET requests from clients - * with limited HTTP configuration options and always receive - * a proper result, even in case of unforeseen errors. + * This makes it easier to do simple GET requests from clients with limited HTTP configuration options. + * It also ensures clients receive a proper result, even in case of unforeseen errors. */ class AcceptJson { diff --git a/src/OrderBy/OrderByServiceProvider.php b/src/OrderBy/OrderByServiceProvider.php index 46e9e0df55..0d5da40659 100644 --- a/src/OrderBy/OrderByServiceProvider.php +++ b/src/OrderBy/OrderByServiceProvider.php @@ -86,9 +86,9 @@ public static function createOrderByClauseInput(string $name, string $descriptio } /** - * We generate this in the same general shape as the input object with columns, - * even though it is unnecessarily complex for this specific case, to make it - * a non-breaking change when columns are added. + * We generate this in the same general shape as the input object with columns. + * It is unnecessarily complex for this specific case. + * This makes it a non-breaking change when columns are added. */ public static function createRelationAggregateFunctionInput(string $name, string $description): InputObjectTypeDefinitionNode { diff --git a/src/Pagination/Cursor.php b/src/Pagination/Cursor.php index d7a7a86e01..f4771497f5 100644 --- a/src/Pagination/Cursor.php +++ b/src/Pagination/Cursor.php @@ -7,7 +7,8 @@ /** * Encode and decode pagination cursors. * - * Currently, the underlying pagination Query uses offset based navigation, so this basically just encodes an offset. + * Currently, the underlying pagination query uses offset-based navigation. + * So this basically just encodes an offset. * This is enough to satisfy the constraints that Relay has, but not a clean permanent solution. * * TODO Implement actual cursor pagination https://github.com/nuwave/lighthouse/issues/311 @@ -17,9 +18,9 @@ class Cursor /** * Decode cursor from query arguments. * - * If no 'after' argument is provided or the contents are not a valid base64 string, - * this will return 0. That will effectively reset pagination, so the user gets the - * first slice. + * If no 'after' argument is provided, this returns 0. + * It also returns 0 if the contents are not a valid base64 string. + * That will effectively reset pagination, so the user gets the first slice. * * @param array $args */ diff --git a/src/Pagination/PaginationManipulator.php b/src/Pagination/PaginationManipulator.php index 7e5d8a6560..71d6cbe0cc 100644 --- a/src/Pagination/PaginationManipulator.php +++ b/src/Pagination/PaginationManipulator.php @@ -22,9 +22,8 @@ class PaginationManipulator /** * The class name of the model that is returned from the field. * - * Might not be present if we are creating a paginated field - * for a relation, as the model is not required for resolving - * that directive and the user may choose a different type. + * This might not be present when creating a paginated field for a relation. + * The model is not required for resolving that directive, and the user may choose a different type. * * @var class-string<\Illuminate\Database\Eloquent\Model>|null */ @@ -364,8 +363,10 @@ protected function pageInfo(): ObjectTypeDefinitionNode * If cache control is used, inherit the max age set in the parent field. * * Pagination adds the nested fields `paginatorInfo` and `data`. - * Cache control identifies this as a new entity, but it should actually not affect the HTTP cache header values. - * Therefore, the @cacheControl directive is applied to inherit whatever max age the parent field set. + * Cache control identifies this as a new entity. + * It should not affect HTTP cache header values. + * Therefore, the @cacheControl directive is applied. + * It inherits whatever max age the parent field set. */ private function maybeInheritCacheControlDirective(): string { diff --git a/src/Schema/AST/ASTHelper.php b/src/Schema/AST/ASTHelper.php index d070cd2786..f1382b3282 100644 --- a/src/Schema/AST/ASTHelper.php +++ b/src/Schema/AST/ASTHelper.php @@ -54,7 +54,7 @@ class ASTHelper * @param \GraphQL\Language\AST\NodeList|array $original * @param \GraphQL\Language\AST\NodeList|array $addition * @param bool $overwriteDuplicates By default, this function throws if a collision occurs. - * If set to true, the fields of the original list will be overwritten. + * If set to true, the fields of the original list will be overwritten. * * @return \GraphQL\Language\AST\NodeList */ @@ -308,9 +308,9 @@ public static function addDirectiveToFields(DirectiveNode $directiveNode, Object /** * Create a fully qualified base for a generated name that belongs to an argument. * - * We have to make sure it is unique in the schema. Even though - * this name becomes a bit verbose, it is also very unlikely to collide - * with a random user defined type. + * We have to make sure it is unique in the schema. + * This name is a bit verbose. + * It is very unlikely to collide with a random user-defined type. * * @example ParentNameFieldNameArgName */ diff --git a/src/Schema/DirectiveLocator.php b/src/Schema/DirectiveLocator.php index 469911e613..3242c81a35 100644 --- a/src/Schema/DirectiveLocator.php +++ b/src/Schema/DirectiveLocator.php @@ -21,8 +21,8 @@ class DirectiveLocator /** * The paths used for locating directive classes. * - * Should be tried in the order they are contained in this array, - * going from the most significant to least significant. + * Should be tried in the order they are contained in this array. + * Go from the most significant to the least significant. * * Lazily initialized. * diff --git a/src/Schema/TypeRegistry.php b/src/Schema/TypeRegistry.php index 2053de5ae6..959e77e743 100644 --- a/src/Schema/TypeRegistry.php +++ b/src/Schema/TypeRegistry.php @@ -242,8 +242,8 @@ public function possibleTypes(): array /** * Get the types that are currently resolved. * - * This does not return all possible types, only those that - * are programmatically registered or already resolved. + * This does not return all possible types. + * It returns only types that are programmatically registered or already resolved. * * @return array */ diff --git a/src/Subscriptions/Directives/SubscriptionDirective.php b/src/Subscriptions/Directives/SubscriptionDirective.php index 428c9ef735..3f1c5ba126 100644 --- a/src/Subscriptions/Directives/SubscriptionDirective.php +++ b/src/Subscriptions/Directives/SubscriptionDirective.php @@ -6,8 +6,7 @@ use Nuwave\Lighthouse\Support\Contracts\Directive; /** - * This directive exists as a placeholder and can be used - * to point to a custom subscription class. + * This directive exists as a placeholder and can be used to point to a custom subscription class. * * @see \Nuwave\Lighthouse\Schema\Types\GraphQLSubscription */ diff --git a/src/Subscriptions/Subscriber.php b/src/Subscriptions/Subscriber.php index 1614dc7fbf..691f5d14cc 100644 --- a/src/Subscriptions/Subscriber.php +++ b/src/Subscriptions/Subscriber.php @@ -16,8 +16,9 @@ class Subscriber /** * A unique key for the subscriber's channel. * - * This has to be unique for each subscriber, because each of them can send a different - * query and must receive a response that is specifically tailored towards that. + * This has to be unique for each subscriber. + * Each of them can send a different query. + * Each must receive a response tailored to that query. */ public string $channel; diff --git a/src/Support/Contracts/ArgDirective.php b/src/Support/Contracts/ArgDirective.php index da02c138af..c65e744c96 100644 --- a/src/Support/Contracts/ArgDirective.php +++ b/src/Support/Contracts/ArgDirective.php @@ -3,7 +3,6 @@ namespace Nuwave\Lighthouse\Support\Contracts; /** - * If this directive is defined on an argument definition that is - * a list, it applies to each item within the list. + * If this directive is defined on a list argument definition, it applies to each list item. */ interface ArgDirective extends Directive {} diff --git a/src/Support/Contracts/ArgDirectiveForArray.php b/src/Support/Contracts/ArgDirectiveForArray.php index 182c0fffaa..5ebbc411c2 100644 --- a/src/Support/Contracts/ArgDirectiveForArray.php +++ b/src/Support/Contracts/ArgDirectiveForArray.php @@ -3,7 +3,7 @@ namespace Nuwave\Lighthouse\Support\Contracts; /** - * This directive can only be used upon a list argument and - * applies to the whole list, not the items inside it. + * This directive can only be used on a list argument. + * It applies to the whole list, not the items inside it. */ interface ArgDirectiveForArray extends Directive {} diff --git a/src/Support/Contracts/Directive.php b/src/Support/Contracts/Directive.php index 66118852a7..eead37b4c0 100644 --- a/src/Support/Contracts/Directive.php +++ b/src/Support/Contracts/Directive.php @@ -9,8 +9,8 @@ interface Directive * * @see https://spec.graphql.org/draft/#sec-Type-System.Directives * - * This must contain a single directive definition, but can also contain - * auxiliary types, such as enum definitions for directive arguments. + * This must contain a single directive definition. + * It may also contain auxiliary types, such as enum definitions for directive arguments. */ public static function definition(): string; } diff --git a/src/Support/Contracts/ProvidesCacheableValidationRules.php b/src/Support/Contracts/ProvidesCacheableValidationRules.php index e8e8a8c042..5ba53e5f48 100644 --- a/src/Support/Contracts/ProvidesCacheableValidationRules.php +++ b/src/Support/Contracts/ProvidesCacheableValidationRules.php @@ -10,8 +10,8 @@ interface ProvidesCacheableValidationRules extends ProvidesValidationRules /** * Rules where the result depends only on the schema and the query string. * - * These rules are executed before non-cacheable rules and may not run - * at all when their result is already cached. + * These rules are executed before non-cacheable rules. + * They may not run at all when their result is already cached. * * @return array */ diff --git a/src/Support/DriverManager.php b/src/Support/DriverManager.php index 92ddb4a5b7..b0a37668d4 100644 --- a/src/Support/DriverManager.php +++ b/src/Support/DriverManager.php @@ -7,8 +7,7 @@ /** * NOTE: Implementation pulled from \Illuminate\Cache\CacheManager. Purpose is - * to serve as a base class to easily generate a manager that creates drivers - * with configuration options. + * to serve as a base class to easily generate a manager that creates drivers with configuration options. * * @phpstan-type CustomCreator callable(\Illuminate\Container\Container $app, array $config): object */ diff --git a/src/WhereConditions/Operator.php b/src/WhereConditions/Operator.php index 7969f21464..97a49b9a64 100644 --- a/src/WhereConditions/Operator.php +++ b/src/WhereConditions/Operator.php @@ -6,8 +6,8 @@ use Illuminate\Database\Query\Builder as QueryBuilder; /** - * An Operator handles the database or application specific bits - * of applying WHERE conditions to a database query builder. + * An Operator handles database- or application-specific details for applying WHERE conditions. + * It applies those conditions to a database query builder. */ interface Operator { diff --git a/src/WhereConditions/WhereConditionsHandler.php b/src/WhereConditions/WhereConditionsHandler.php index 39fe7ddf70..08304b37a9 100644 --- a/src/WhereConditions/WhereConditionsHandler.php +++ b/src/WhereConditions/WhereConditionsHandler.php @@ -119,8 +119,8 @@ public static function invalidColumnName(string $column): string /** * If the condition references a column, prefix it with the table name. * - * This is important for queries which can otherwise be ambiguous, for - * example when multiple tables with a column "id" are involved. + * This is important for queries that can otherwise be ambiguous. + * For example, ambiguity happens when multiple tables include a column named "id". * * @param array $condition * diff --git a/src/lighthouse.php b/src/lighthouse.php index 01b14ad781..cd56d17277 100644 --- a/src/lighthouse.php +++ b/src/lighthouse.php @@ -24,8 +24,8 @@ 'name' => 'graphql', /* - * Beware that middleware defined here runs before the GraphQL execution phase, - * make sure to return spec-compliant responses in case an error is thrown. + * Beware that middleware defined here runs before the GraphQL execution phase. + * Make sure to return spec-compliant responses in case an error is thrown. */ 'middleware' => [ // Ensures the request is not vulnerable to cross-site request forgery. @@ -433,7 +433,7 @@ /* * Default subscription storage time to live in seconds. * - * Indicates how long a subscription can be active before it's automatically removed from storage. + * Indicates how long a subscription can stay active before automatic removal from storage. * Setting this to `null` means the subscriptions are stored forever. This may cause * stale subscriptions to linger indefinitely in case cleanup fails for any reason. */ @@ -475,7 +475,8 @@ /* * Should the subscriptions extension be excluded when the response has no subscription channel? - * This optimizes performance by sending less data, but clients must anticipate this appropriately. + * This optimizes performance by sending less data. + * Clients must anticipate this behavior. */ 'exclude_empty' => env('LIGHTHOUSE_SUBSCRIPTION_EXCLUDE_EMPTY', true), ], diff --git a/tests/TestCase.php b/tests/TestCase.php index 24f1c8e720..a34686617c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -185,8 +185,8 @@ protected function getEnvironmentSetUp($app): void /** * Rethrow all errors that are not handled by GraphQL. * - * This makes debugging the tests much simpler as Exceptions - * are fully dumped to the console when making requests. + * This makes test debugging much simpler. + * Exceptions are fully dumped to the console when making requests. */ protected function resolveApplicationExceptionHandler($app): void { diff --git a/tests/Unit/Federation/SchemaBuilderTest.php b/tests/Unit/Federation/SchemaBuilderTest.php index 5eb3e43e80..10ff25e2ef 100644 --- a/tests/Unit/Federation/SchemaBuilderTest.php +++ b/tests/Unit/Federation/SchemaBuilderTest.php @@ -64,8 +64,8 @@ private function assertSchemaHasQueryTypeWithFederationFields(Schema $schema): v /** * At least one type needs to be defined with the @key directive. * - * We could also just not add the type definition below if no entities match, - * so the user themselves is responsible to add the _Entity union. + * We could also omit the type definition below when no entities match. + * In that case, the user is responsible for adding the _Entity union. * In this case, GraphQL validation will throw an exception if the union is missing. */ public function testThrowsIfNoTypeHasKeyDirective(): void diff --git a/tests/Unit/Schema/Directives/BaseDirectiveTest.php b/tests/Unit/Schema/Directives/BaseDirectiveTest.php index c3f3ed3037..f412dd66cf 100644 --- a/tests/Unit/Schema/Directives/BaseDirectiveTest.php +++ b/tests/Unit/Schema/Directives/BaseDirectiveTest.php @@ -16,10 +16,11 @@ /** * This class does test the internal behavior of the BaseDirective class. * - * While typically considered an anti-pattern, the BaseDirective is meant - * to be extended by other directives and offers basic utilities that - * are commonly used in directives. As users may also extend it to create - * custom directives, its behavior should be stable and well-defined. + * This is typically considered an anti-pattern. + * BaseDirective is meant to be extended by other directives. + * It offers basic utilities that are commonly used in directives. + * Users may also extend it to create custom directives. + * Its behavior should be stable and well-defined. */ final class BaseDirectiveTest extends TestCase { diff --git a/tests/Utils/Models/Closure.php b/tests/Utils/Models/Closure.php index 96e8541cda..9731f17676 100644 --- a/tests/Utils/Models/Closure.php +++ b/tests/Utils/Models/Closure.php @@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Model; /** - * This model is used for checking that classes that are named like a - * base PHP class can be correctly resolved. + * This model checks that classes named like base PHP classes can be resolved correctly. */ final class Closure extends Model {} diff --git a/tests/Utils/ModelsSecondary/Category.php b/tests/Utils/ModelsSecondary/Category.php index 3b5df4a72b..8624c777c4 100644 --- a/tests/Utils/ModelsSecondary/Category.php +++ b/tests/Utils/ModelsSecondary/Category.php @@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model; /** - * This class is named the same as a model in the primary namespace, - * so it will only be used if the namespace is explicitly given. + * This class has the same name as a model in the primary namespace. + * It will only be used if the namespace is explicitly given. */ final class Category extends Model {} diff --git a/tests/Utils/Mutations/Foo.php b/tests/Utils/Mutations/Foo.php index 92f716a404..6e9acc1218 100644 --- a/tests/Utils/Mutations/Foo.php +++ b/tests/Utils/Mutations/Foo.php @@ -3,8 +3,8 @@ namespace Tests\Utils\Mutations; /** - * This is used solely as a placeholder resolver, as schemas without a valid - * field in the query type are invalid. + * This is used solely as a placeholder resolver. + * Schemas without a valid field in the query type are invalid. */ final class Foo { diff --git a/tests/Utils/Queries/Foo.php b/tests/Utils/Queries/Foo.php index 1400d6ff41..027a6530e7 100644 --- a/tests/Utils/Queries/Foo.php +++ b/tests/Utils/Queries/Foo.php @@ -3,8 +3,8 @@ namespace Tests\Utils\Queries; /** - * This is used solely as a placeholder resolver, as schemas without a valid - * field in the query type are invalid. + * This is used solely as a placeholder resolver. + * Schemas without a valid field in the query type are invalid. */ final class Foo {