diff --git a/_lighthouse_ide_helper.php b/_lighthouse_ide_helper.php new file mode 100644 index 0000000..2c66b8b --- /dev/null +++ b/_lighthouse_ide_helper.php @@ -0,0 +1,157 @@ + $keys the validation keys the result should have + * + * @return $this + */ + public function assertGraphQLValidationKeys(array $keys): self + { + return $this; + } + + /** + * Assert that a given validation error is present in the response. + * + * @param string $key the validation key that should be present + * @param string $message the expected validation message + * + * @return $this + */ + public function assertGraphQLValidationError(string $key, string $message): self + { + return $this; + } + + /** + * Assert that no validation errors are present in the response. + * + * @return $this + */ + public function assertGraphQLValidationPasses(): self + { + return $this; + } + } +} + +namespace Illuminate\Testing { + class TestResponse + { + /** + * Assert the response contains an error with a matching message. + * + * @param \Throwable $error the expected error + * + * @return $this + */ + public function assertGraphQLError(\Throwable $error): self + { + return $this; + } + + /** + * Assert the response contains an error with the given message. + * + * @param string $message the expected error message + * + * @return $this + */ + public function assertGraphQLErrorMessage(string $message): self + { + return $this; + } + + /** + * Assert the response contains an error with the given debug message. + * + * Requires the config `lighthouse.debug` to include the option \GraphQL\Error\DebugFlag::INCLUDE_DEBUG_MESSAGE. + * + * @param string $message the expected debug message + * + * @return $this + */ + public function assertGraphQLDebugMessage(string $message): self + { + return $this; + } + + /** + * Assert the response contains no errors. + * + * @return $this + */ + public function assertGraphQLErrorFree(): self + { + return $this; + } + + /** + * Assert the response contains an error from the given category. + * + * @param string $category the name of the expected error category + * + * @return $this + */ + public function assertGraphQLErrorCategory(string $category): self + { + return $this; + } + + /** + * Assert the returned result contains exactly the given validation keys. + * + * @param array $keys the validation keys the result should have + * + * @return $this + */ + public function assertGraphQLValidationKeys(array $keys): self + { + return $this; + } + + /** + * Assert a given validation error is present in the response. + * + * @param string $key the validation key that should be present + * @param string $message the expected validation message + * + * @return $this + */ + public function assertGraphQLValidationError(string $key, string $message): self + { + return $this; + } + + /** + * Assert no validation errors are present in the response. + * + * @return $this + */ + public function assertGraphQLValidationPasses(): self + { + return $this; + } + } +} diff --git a/app/GraphQL/Mutations/Post/CreatePostMutation.php b/app/GraphQL/Mutations/Post/CreatePostMutation.php new file mode 100644 index 0000000..d440c6c --- /dev/null +++ b/app/GraphQL/Mutations/Post/CreatePostMutation.php @@ -0,0 +1,16 @@ + 'comment', + ]; + + /** + * @return Type + */ + public function type(): Type + { + return GraphQL::type('Comment'); + } + + public function args(): array + { + return [ + 'id' => [ + 'name' => 'id', + 'type' => Type::int(), + 'rules' => ['required'] + ] + ]; + } + + public function resolve($root, $args) + { + return Comment::findOrFail($args['id']); + } +} diff --git a/app/GraphQL/Queries/Comment/CommentsQuery.php b/app/GraphQL/Queries/Comment/CommentsQuery.php new file mode 100644 index 0000000..839bf91 --- /dev/null +++ b/app/GraphQL/Queries/Comment/CommentsQuery.php @@ -0,0 +1,42 @@ + 'comments', + ]; + + public function type(): Type + { + return Type::listOf(GraphQL::type('Comment')); + } + + public function args(): array + { + return [ + 'id' => [ + 'name' => 'id', + 'type' => Type::int(), + 'rules' => ['required'] + ] + ]; + } + + /** + * @param $root + * @param $args + * @return Collection + */ + public function resolve($root, $args): Collection + { + return Comment::all(); + } +} diff --git a/app/GraphQL/Queries/Post/PostQuery.php b/app/GraphQL/Queries/Post/PostQuery.php new file mode 100644 index 0000000..e697e89 --- /dev/null +++ b/app/GraphQL/Queries/Post/PostQuery.php @@ -0,0 +1,39 @@ + 'post', + ]; + + /** + * @return Type + */ + public function type(): Type + { + return GraphQL::type('Post'); + } + + public function args(): array + { + return [ + 'id' => [ + 'name' => 'id', + 'type' => Type::int(), + 'rules' => ['required'] + ] + ]; + } + + public function resolve($root, $args) + { + return Post::findOrFail($args['id']); + } +} diff --git a/app/GraphQL/Queries/Post/PostsQuery.php b/app/GraphQL/Queries/Post/PostsQuery.php new file mode 100644 index 0000000..ef6bb51 --- /dev/null +++ b/app/GraphQL/Queries/Post/PostsQuery.php @@ -0,0 +1,32 @@ + 'posts', + ]; + + public function type(): Type + { + return Type::listOf(GraphQL::type('Post')); + } + + /** + * @param $root + * @param $args + * @return Collection + */ + public function resolve($root, $args): Collection + { + return Post::all(); + } +} diff --git a/app/GraphQL/Types/CommentType.php b/app/GraphQL/Types/CommentType.php new file mode 100644 index 0000000..e546103 --- /dev/null +++ b/app/GraphQL/Types/CommentType.php @@ -0,0 +1,30 @@ + 'Comment', + 'description' => 'Collection of comments', + 'model' => Comment::class + ]; + + public function fields(): array + { + return [ + 'id' => [ + 'type' => Type::nonNull(Type::int()), + 'description' => 'ID of comment' + ], + 'body' => [ + 'type' => Type::nonNull(Type::string()), + 'description' => 'Body of the comment' + ], + ]; + } +} diff --git a/app/GraphQL/Types/PostType.php b/app/GraphQL/Types/PostType.php new file mode 100644 index 0000000..94abf29 --- /dev/null +++ b/app/GraphQL/Types/PostType.php @@ -0,0 +1,43 @@ + 'Post', + 'description' => 'Collection of posts', + 'model' => Post::class + ]; + + public function fields(): array + { + return [ + 'id' => [ + 'type' => Type::nonNull(Type::int()), + 'description' => 'ID of post' + ], + 'title' => [ + 'type' => Type::nonNull(Type::string()), + 'description' => 'Title of the post' + ], + 'image' => [ + 'type' => Type::nonNull(Type::string()), + 'description' => 'Image of the post' + ], + 'content' => [ + 'type' => Type::nonNull(Type::string()), + 'description' => 'Content of the post' + ], + 'comments' => [ + 'type' => Type::listOf(GraphQL::type('Comment')), + 'description' => 'List of comments' + ] + ]; + } +} diff --git a/app/Http/Controllers/API/APIController.php b/app/Http/Controllers/API/APIController.php new file mode 100644 index 0000000..194c3e8 --- /dev/null +++ b/app/Http/Controllers/API/APIController.php @@ -0,0 +1,44 @@ +json(['status' => $status, 'message' => $message, 'data' => $data], $status, [], JSON_UNESCAPED_UNICODE); + } + + /** + * @param array $data + * @param array $errors + * @param string $message + * @param int $status + * @return JsonResponse + */ + public function errorResponse(array $data, array $errors, string $message, int $status = 422): JsonResponse + { + return response()->json(['status' => $status, 'message' => $message, 'data' => $data, 'errors' => $this->formatValidationErrors($errors)]); + + } + + + /** + * @param array $errors + * @return array + */ + private function formatValidationErrors(array $errors): array + { + return array_values($errors); + } +} diff --git a/app/Http/Controllers/API/PostController.php b/app/Http/Controllers/API/PostController.php new file mode 100644 index 0000000..0297a63 --- /dev/null +++ b/app/Http/Controllers/API/PostController.php @@ -0,0 +1,12 @@ + [ - // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, + \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], diff --git a/app/Http/Services/PostService.php b/app/Http/Services/PostService.php new file mode 100644 index 0000000..434b3c1 --- /dev/null +++ b/app/Http/Services/PostService.php @@ -0,0 +1,11 @@ +=5.3" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "~9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "HaydenPierce\\ClassFinder\\": "src/", + "HaydenPierce\\ClassFinder\\UnitTest\\": "test/unit" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Hayden Pierce", + "email": "hayden@haydenpierce.com" + } + ], + "description": "A library that can provide of a list of classes in a given namespace", + "time": "2022-09-26T22:42:59+00:00" + }, + { + "name": "laragraph/utils", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/laragraph/utils.git", + "reference": "8e4d4833b5317a23584a365ef224e1cb813fd72e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laragraph/utils/zipball/8e4d4833b5317a23584a365ef224e1cb813fd72e", + "reference": "8e4d4833b5317a23584a365ef224e1cb813fd72e", + "shasum": "" + }, + "require": { + "illuminate/contracts": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/http": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "php": "^7.2 || ^8", + "thecodingmachine/safe": "^1.1 || ^2", + "webonyx/graphql-php": "^0.13.2 || ^14 || ^15" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.11", + "jangregor/phpstan-prophecy": "^1", + "mll-lab/php-cs-fixer-config": "^4.4", + "orchestra/testbench": "3.6.* || 3.7.* || 3.8.* || 3.9.* || ^4 || ^5 || ^6 || ^7", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^1", + "phpstan/phpstan-deprecation-rules": "^1", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9", + "thecodingmachine/phpstan-safe-rule": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Laragraph\\Utils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benedikt Franke", + "email": "benedikt@franke.tech" + } + ], + "description": "Utilities for using GraphQL with Laravel", + "homepage": "https://github.com/laragraph/utils", + "support": { + "issues": "https://github.com/laragraph/utils/issues", + "source": "https://github.com/laragraph/utils" + }, + "time": "2023-01-13T08:46:49+00:00" + }, { "name": "laravel/framework", "version": "v9.48.0", @@ -1719,6 +1819,125 @@ ], "time": "2022-04-17T13:12:02+00:00" }, + { + "name": "mll-lab/laravel-graphiql", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/mll-lab/laravel-graphiql.git", + "reference": "3284c7d2f2dc64c3ccd3bae5bd95519baa9b0394" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mll-lab/laravel-graphiql/zipball/3284c7d2f2dc64c3ccd3bae5bd95519baa9b0394", + "reference": "3284c7d2f2dc64c3ccd3bae5bd95519baa9b0394", + "shasum": "" + }, + "require": { + "illuminate/console": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/contracts": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/support": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "php": "^7.1 || ^8" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2", + "laravel/lumen-framework": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "mll-lab/php-cs-fixer-config": "^4.4" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "MLL\\GraphiQL\\GraphiQLServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "MLL\\GraphiQL\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benedikt Franke", + "email": "benedikt@franke.tech" + } + ], + "description": "Easily integrate GraphiQL into your Laravel project", + "keywords": [ + "graphiql", + "graphql", + "laravel" + ], + "support": { + "issues": "https://github.com/mll-lab/laravel-graphiql/issues", + "source": "https://github.com/mll-lab/laravel-graphiql/tree/v1.0.1" + }, + "time": "2022-09-08T07:32:28+00:00" + }, + { + "name": "mll-lab/laravel-graphql-playground", + "version": "v2.6.0", + "source": { + "type": "git", + "url": "https://github.com/mll-lab/laravel-graphql-playground.git", + "reference": "f3c56d80220211cdb736356ffe9a14ebcfc0ec88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mll-lab/laravel-graphql-playground/zipball/f3c56d80220211cdb736356ffe9a14ebcfc0ec88", + "reference": "f3c56d80220211cdb736356ffe9a14ebcfc0ec88", + "shasum": "" + }, + "require": { + "illuminate/console": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/contracts": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/support": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "php": "^7.1 || ^8" + }, + "require-dev": { + "laravel/lumen-framework": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "localheinz/composer-normalize": "^1.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "MLL\\GraphQLPlayground\\GraphQLPlaygroundServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "MLL\\GraphQLPlayground\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benedikt Franke", + "email": "benedikt@franke.tech" + } + ], + "description": "Easily integrate GraphQL Playground into your Laravel project", + "keywords": [ + "graphql", + "graphql-playground", + "laravel" + ], + "support": { + "issues": "https://github.com/mll-lab/laravel-graphql-playground/issues", + "source": "https://github.com/mll-lab/laravel-graphql-playground/tree/v2.6.0" + }, + "time": "2022-02-08T15:58:46+00:00" + }, { "name": "monolog/monolog", "version": "2.8.0", @@ -2213,6 +2432,134 @@ ], "time": "2022-12-20T19:00:15+00:00" }, + { + "name": "nuwave/lighthouse", + "version": "v5.70.2", + "source": { + "type": "git", + "url": "https://github.com/nuwave/lighthouse.git", + "reference": "bc515ffeaa74c86fa4f37e852974f8451ea3d885" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nuwave/lighthouse/zipball/bc515ffeaa74c86fa4f37e852974f8451ea3d885", + "reference": "bc515ffeaa74c86fa4f37e852974f8451ea3d885", + "shasum": "" + }, + "require": { + "ext-json": "*", + "haydenpierce/class-finder": "^0.4", + "illuminate/auth": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/bus": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/contracts": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/http": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/pagination": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/queue": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/routing": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/support": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "illuminate/validation": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "laragraph/utils": "^1", + "php": ">= 7.2", + "thecodingmachine/safe": "^1 || ^2", + "webonyx/graphql-php": "^14.7" + }, + "require-dev": { + "algolia/algoliasearch-client-php": "^3 || ^4", + "bensampo/laravel-enum": "^1.28.3 || ^2 || ^3 || ^4 || ^5 || ^6", + "ergebnis/composer-normalize": "^2.2.2", + "laravel/framework": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9", + "laravel/legacy-factories": "^1", + "laravel/lumen-framework": "5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9 || dev-master", + "laravel/scout": "^7 || ^8 || ^9", + "mll-lab/graphql-php-scalars": "^4 || ^5", + "mll-lab/php-cs-fixer-config": "^4.4.1", + "mockery/mockery": "^1", + "nunomaduro/larastan": "^0.6 || ^0.7 || ^1 || ^2", + "orchestra/testbench": "3.6.* || 3.7.* || 3.8.* || 3.9.* || ^4 || ^5 || ^6 || ^7", + "phpbench/phpbench": "^1", + "phpstan/phpstan": "~0.12 || ^1", + "phpstan/phpstan-mockery": "~0.12 || ^1", + "phpstan/phpstan-phpunit": "~0.12 || ^1", + "phpunit/phpunit": "^7.5 || ^8.4 || ^9", + "predis/predis": "^1.1", + "pusher/pusher-php-server": "^4 || ^5 || ^6 || ^7", + "rector/rector": "^0.12", + "thecodingmachine/phpstan-safe-rule": "^1" + }, + "suggest": { + "bensampo/laravel-enum": "Convenient enum definitions that can easily be registered in your Schema", + "laravel/scout": "Required for the @search directive", + "mll-lab/graphql-php-scalars": "Useful scalar types, required for @whereConditions", + "mll-lab/laravel-graphiql": "A graphical interactive in-browser GraphQL IDE - integrated with Laravel", + "pusher/pusher-php-server": "Required when using the Pusher Subscriptions driver" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "graphql": "Nuwave\\Lighthouse\\GraphQL" + }, + "providers": [ + "Nuwave\\Lighthouse\\LighthouseServiceProvider", + "Nuwave\\Lighthouse\\Auth\\AuthServiceProvider", + "Nuwave\\Lighthouse\\Cache\\CacheServiceProvider", + "Nuwave\\Lighthouse\\GlobalId\\GlobalIdServiceProvider", + "Nuwave\\Lighthouse\\OrderBy\\OrderByServiceProvider", + "Nuwave\\Lighthouse\\Pagination\\PaginationServiceProvider", + "Nuwave\\Lighthouse\\Scout\\ScoutServiceProvider", + "Nuwave\\Lighthouse\\SoftDeletes\\SoftDeletesServiceProvider", + "Nuwave\\Lighthouse\\Validation\\ValidationServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Nuwave\\Lighthouse\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christopher Moore", + "email": "chris@nuwavecommerce.com", + "homepage": "https://www.nuwavecommerce.com" + }, + { + "name": "Benedikt Franke", + "email": "benedikt@franke.tech", + "homepage": "https://franke.tech" + } + ], + "description": "A framework for serving GraphQL from Laravel", + "homepage": "https://lighthouse-php.com", + "keywords": [ + "graphql", + "laravel", + "laravel-graphql" + ], + "support": { + "issues": "https://github.com/nuwave/lighthouse/issues", + "source": "https://github.com/nuwave/lighthouse" + }, + "funding": [ + { + "url": "https://github.com/spawnia", + "type": "github" + }, + { + "url": "https://issuehunt.io/r/nuwave/lighthouse", + "type": "issuehunt" + }, + { + "url": "https://www.patreon.com/lighthouse_php", + "type": "patreon" + } + ], + "time": "2023-01-23T13:07:54+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.0", @@ -2953,6 +3300,112 @@ ], "time": "2023-01-12T18:13:24+00:00" }, + { + "name": "rebing/graphql-laravel", + "version": "8.5.0", + "source": { + "type": "git", + "url": "https://github.com/rebing/graphql-laravel.git", + "reference": "2db66927f5877f03279ec95f9da0acf39ff130e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rebing/graphql-laravel/zipball/2db66927f5877f03279ec95f9da0acf39ff130e3", + "reference": "2db66927f5877f03279ec95f9da0acf39ff130e3", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/contracts": "^6.0|^8.0|^9.0", + "illuminate/support": "^6.0|^8.0|^9.0", + "laragraph/utils": "^1", + "php": ">= 7.4", + "thecodingmachine/safe": "^1.1|^2.4", + "webonyx/graphql-php": "^14.6.4" + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "friendsofphp/php-cs-fixer": "3.11.0", + "laravel/legacy-factories": "^1.0", + "mfn/php-cs-fixer-config": "^2", + "mockery/mockery": "^1.2", + "nunomaduro/larastan": "1.0.3", + "orchestra/testbench": "4.0.*|5.0.*|^6.0|^7.0", + "phpstan/phpstan": "1.8.4", + "phpunit/phpunit": "~7.0|~8.0|^9", + "thecodingmachine/phpstan-safe-rule": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.5-dev" + }, + "laravel": { + "providers": [ + "Rebing\\GraphQL\\GraphQLServiceProvider" + ], + "aliases": { + "GraphQL": "Rebing\\GraphQL\\Support\\Facades\\GraphQL" + } + } + }, + "autoload": { + "psr-4": { + "Rebing\\GraphQL\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rebing OÜ", + "homepage": "http://www.rebing.ee", + "role": "Company" + }, + { + "name": "Mikk Mihkel Nurges", + "email": "mikk.nurges@rebing.ee", + "role": "Developer" + }, + { + "name": "Folklore", + "email": "info@atelierfolklore.ca", + "homepage": "http://atelierfolklore.ca" + }, + { + "name": "David Mongeau-Petitpas", + "email": "dmp@atelierfolklore.ca", + "homepage": "http://mongo.ca", + "role": "Developer" + }, + { + "name": "Markus Podar", + "email": "markus@fischer.name", + "homepage": "https://github.com/mfn", + "role": "Developer" + } + ], + "description": "Laravel wrapper for PHP GraphQL", + "keywords": [ + "framework", + "graphql", + "laravel", + "react" + ], + "support": { + "issues": "https://github.com/rebing/graphql-laravel/issues", + "source": "https://github.com/rebing/graphql-laravel/tree/8.5.0" + }, + "funding": [ + { + "url": "https://github.com/mfn", + "type": "github" + } + ], + "time": "2023-01-13T08:09:51+00:00" + }, { "name": "symfony/console", "version": "v6.2.3", @@ -5148,6 +5601,145 @@ ], "time": "2022-12-22T17:55:15+00:00" }, + { + "name": "thecodingmachine/safe", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "e788f3d09dcd36f806350aedb77eac348fafadd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/e788f3d09dcd36f806350aedb77eac348fafadd3", + "reference": "e788f3d09dcd36f806350aedb77eac348fafadd3", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "files": [ + "deprecated/apc.php", + "deprecated/array.php", + "deprecated/datetime.php", + "deprecated/libevent.php", + "deprecated/misc.php", + "deprecated/password.php", + "deprecated/mssql.php", + "deprecated/stats.php", + "deprecated/strings.php", + "lib/special_cases.php", + "deprecated/mysqli.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "classmap": [ + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "deprecated/Exceptions/", + "generated/Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v2.4.0" + }, + "time": "2022-10-07T14:02:17+00:00" + }, { "name": "tijsverkoyen/css-to-inline-styles", "version": "2.2.6", @@ -5416,6 +6008,72 @@ "source": "https://github.com/webmozarts/assert/tree/1.11.0" }, "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "webonyx/graphql-php", + "version": "v14.11.9", + "source": { + "type": "git", + "url": "https://github.com/webonyx/graphql-php.git", + "reference": "ff91c9f3cf241db702e30b2c42bcc0920e70ac70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/ff91c9f3cf241db702e30b2c42bcc0920e70ac70", + "reference": "ff91c9f3cf241db702e30b2c42bcc0920e70ac70", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^7.1 || ^8" + }, + "require-dev": { + "amphp/amp": "^2.3", + "doctrine/coding-standard": "^6.0", + "nyholm/psr7": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "0.12.82", + "phpstan/phpstan-phpunit": "0.12.18", + "phpstan/phpstan-strict-rules": "0.12.9", + "phpunit/phpunit": "^7.2 || ^8.5", + "psr/http-message": "^1.0", + "react/promise": "2.*", + "simpod/php-coveralls-mirror": "^3.0", + "squizlabs/php_codesniffer": "3.5.4" + }, + "suggest": { + "psr/http-message": "To use standard GraphQL server", + "react/promise": "To leverage async resolving on React PHP platform" + }, + "type": "library", + "autoload": { + "psr-4": { + "GraphQL\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP port of GraphQL reference implementation", + "homepage": "https://github.com/webonyx/graphql-php", + "keywords": [ + "api", + "graphql" + ], + "support": { + "issues": "https://github.com/webonyx/graphql-php/issues", + "source": "https://github.com/webonyx/graphql-php/tree/v14.11.9" + }, + "funding": [ + { + "url": "https://opencollective.com/webonyx-graphql-php", + "type": "open_collective" + } + ], + "time": "2023-01-06T12:12:50+00:00" } ], "packages-dev": [ @@ -7872,7 +8530,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.0.2" + "php": "^8.0.2", + "ext-fileinfo": "*" }, "platform-dev": [], "plugin-api-version": "2.3.0" diff --git a/config/graphql.php b/config/graphql.php new file mode 100644 index 0000000..31a9507 --- /dev/null +++ b/config/graphql.php @@ -0,0 +1,237 @@ + [ + // The prefix for routes; do NOT use a leading slash! + 'prefix' => 'graphql', + + // The controller/method to use in GraphQL request. + // Also supported array syntax: `[\Rebing\GraphQL\GraphQLController::class, 'query']` + 'controller' => \Rebing\GraphQL\GraphQLController::class . '@query', + + // Any middleware for the graphql route group + // This middleware will apply to all schemas + 'middleware' => [], + + // Additional route group attributes + // + // Example: + // + // 'group_attributes' => ['guard' => 'api'] + // + 'group_attributes' => [], + ], + + // The name of the default schema + // Used when the route group is directly accessed + 'default_schema' => 'default', + + 'batching' => [ + // Whether to support GraphQL batching or not. + // See e.g. https://www.apollographql.com/blog/batching-client-graphql-queries-a685f5bcd41b/ + // for pro and con + 'enable' => true, + ], + + // The schemas for query and/or mutation. It expects an array of schemas to provide + // both the 'query' fields and the 'mutation' fields. + // + // You can also provide a middleware that will only apply to the given schema + // + // Example: + // + // 'schemas' => [ + // 'default' => [ + // 'controller' => MyController::class . '@method', + // 'query' => [ + // App\GraphQL\Queries\UsersQuery::class, + // ], + // 'mutation' => [ + // + // ] + // ], + // 'user' => [ + // 'query' => [ + // App\GraphQL\Queries\ProfileQuery::class, + // ], + // 'mutation' => [ + // + // ], + // 'middleware' => ['auth'], + // ], + // 'user/me' => [ + // 'query' => [ + // App\GraphQL\Queries\MyProfileQuery::class, + // ], + // 'mutation' => [ + // + // ], + // 'middleware' => ['auth'], + // ], + // ] + // + 'schemas' => [ + 'default' => [ + 'query' => [ + 'post' => \App\GraphQL\Queries\Post\PostQuery::class, + 'posts' => \App\GraphQL\Queries\Post\PostsQuery::class, + 'comment' => \App\GraphQL\Queries\Comment\CommentQuery::class, + 'comments' => \App\GraphQL\Queries\Comment\CommentsQuery::class + ], + 'mutation' => [ + 'createPost' => \App\GraphQL\Mutations\Post\CreatePostMutation::class + ], + // The types only available in this schema + 'types' => [ + 'Post' => \App\GraphQL\Types\PostType::class, + 'Comment' => \App\GraphQL\Types\CommentType::class + ], + + // Laravel HTTP middleware + 'middleware' => null, + + // Which HTTP methods to support; must be given in UPPERCASE! + 'method' => ['GET', 'POST'], + + // An array of middlewares, overrides the global ones + 'execution_middleware' => null, + ], + ], + + // The global types available to all schemas. + // You can then access it from the facade like this: GraphQL::type('user') + // + // Example: + // + // 'types' => [ + // App\GraphQL\Types\UserType::class + // ] + // + 'types' => [ + // ExampleType::class, + // ExampleRelationType::class, + // \Rebing\GraphQL\Support\UploadType::class, + ], + + // The types will be loaded on demand. Default is to load all types on each request + // Can increase performance on schemes with many types + // Presupposes the config type key to match the type class name property + 'lazyload_types' => true, + + // This callable will be passed the Error object for each errors GraphQL catch. + // The method should return an array representing the error. + // Typically: + // [ + // 'message' => '', + // 'locations' => [] + // ] + 'error_formatter' => [\Rebing\GraphQL\GraphQL::class, 'formatError'], + + /* + * Custom Error Handling + * + * Expected handler signature is: function (array $errors, callable $formatter): array + * + * The default handler will pass exceptions to laravel Error Handling mechanism + */ + 'errors_handler' => [\Rebing\GraphQL\GraphQL::class, 'handleErrors'], + + /* + * Options to limit the query complexity and depth. See the doc + * @ https://webonyx.github.io/graphql-php/security + * for details. Disabled by default. + */ + 'security' => [ + 'query_max_complexity' => null, + 'query_max_depth' => null, + 'disable_introspection' => false, + ], + + /* + * You can define your own pagination type. + * Reference \Rebing\GraphQL\Support\PaginationType::class + */ + 'pagination_type' => \Rebing\GraphQL\Support\PaginationType::class, + + /* + * You can define your own simple pagination type. + * Reference \Rebing\GraphQL\Support\SimplePaginationType::class + */ + 'simple_pagination_type' => \Rebing\GraphQL\Support\SimplePaginationType::class, + + /* + * Config for GraphiQL (see (https://github.com/graphql/graphiql). + */ + 'graphiql' => [ + 'prefix' => 'graphiql', // Do NOT use a leading slash + 'controller' => \Rebing\GraphQL\GraphQLController::class . '@graphiql', + 'middleware' => [], + 'view' => 'graphql::graphiql', + 'display' => env('ENABLE_GRAPHIQL', true), + ], + + /* + * Overrides the default field resolver + * See http://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver + * + * Example: + * + * ```php + * 'defaultFieldResolver' => function ($root, $args, $context, $info) { + * }, + * ``` + * or + * ```php + * 'defaultFieldResolver' => [SomeKlass::class, 'someMethod'], + * ``` + */ + 'defaultFieldResolver' => null, + + /* + * Any headers that will be added to the response returned by the default controller + */ + 'headers' => [], + + /* + * Any JSON encoding options when returning a response from the default controller + * See http://php.net/manual/function.json-encode.php for the full list of options + */ + 'json_encoding_options' => 0, + + /* + * Automatic Persisted Queries (APQ) + * See https://www.apollographql.com/docs/apollo-server/performance/apq/ + * + * Note 1: this requires the `AutomaticPersistedQueriesMiddleware` being enabled + * + * Note 2: even if APQ is disabled per configuration and, according to the "APQ specs" (see above), + * to return a correct response in case it's not enabled, the middleware needs to be active. + * Of course if you know you do not have a need for APQ, feel free to remove the middleware completely. + */ + 'apq' => [ + // Enable/Disable APQ - See https://www.apollographql.com/docs/apollo-server/performance/apq/#disabling-apq + 'enable' => env('GRAPHQL_APQ_ENABLE', false), + + // The cache driver used for APQ + 'cache_driver' => env('GRAPHQL_APQ_CACHE_DRIVER', config('cache.default')), + + // The cache prefix + 'cache_prefix' => config('cache.prefix') . ':graphql.apq', + + // The cache ttl in seconds - See https://www.apollographql.com/docs/apollo-server/performance/apq/#adjusting-cache-time-to-live-ttl + 'cache_ttl' => 300, + ], + + /* + * Execution middlewares + */ + 'execution_middleware' => [ + \Rebing\GraphQL\Support\ExecutionMiddleware\ValidateOperationParamsMiddleware::class, + // AutomaticPersistedQueriesMiddleware listed even if APQ is disabled, see the docs for the `'apq'` configuration + \Rebing\GraphQL\Support\ExecutionMiddleware\AutomaticPersistedQueriesMiddleware::class, + \Rebing\GraphQL\Support\ExecutionMiddleware\AddAuthUserContextValueMiddleware::class, + // \Rebing\GraphQL\Support\ExecutionMiddleware\UnusedVariablesMiddleware::class, + ], +]; diff --git a/config/lighthouse.php b/config/lighthouse.php new file mode 100644 index 0000000..c23fdf0 --- /dev/null +++ b/config/lighthouse.php @@ -0,0 +1,520 @@ + false, to disable the default route + | registration and take full control. + | + */ + + 'route' => [ + /* + * The URI the endpoint responds to, e.g. mydomain.com/graphql. + */ + 'uri' => '/graphql', + + /* + * Lighthouse creates a named route for convenient URL generation and redirects. + */ + '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. + */ + 'middleware' => [ + \Nuwave\Lighthouse\Support\Http\Middleware\AcceptJson::class, + + // Logs in a user if they are authenticated. In contrast to Laravel's 'auth' + // middleware, this delegates auth and permission checks to the field level. + \Nuwave\Lighthouse\Support\Http\Middleware\AttemptAuthentication::class, + + // Logs every incoming GraphQL query. + // \Nuwave\Lighthouse\Support\Http\Middleware\LogGraphQLQueries::class, + ], + + /* + * The `prefix`, `domain` and `where` configuration options are optional. + */ + // 'prefix' => '', + // 'domain' => '', + // 'where' => [], + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guard + |-------------------------------------------------------------------------- + | + | The guard to use for authenticating GraphQL requests, if needed. + | Used in directives such as `@guard` or the `AttemptAuthentication` middleware. + | Falls back to the Laravel default if the defined guard is either `null` or not found. + | + */ + + 'guard' => 'api', + + /* + |-------------------------------------------------------------------------- + | Schema Location + |-------------------------------------------------------------------------- + | + | Path to your .graphql schema file. + | Additional schema files may be imported from within that file. + | + */ + + 'schema' => [ + 'register' => base_path('graphql/schema.graphql'), + ], + + /* + |-------------------------------------------------------------------------- + | Schema Cache + |-------------------------------------------------------------------------- + | + | A large part of schema generation consists of parsing and AST manipulation. + | This operation is very expensive, so it is highly recommended enabling + | caching of the final schema to optimize performance of large schemas. + | + */ + + 'cache' => [ + /* + * Setting to true enables schema caching. + */ + 'enable' => env('LIGHTHOUSE_CACHE_ENABLE', 'local' !== env('APP_ENV')), + + /* + * Allowed values: + * - 1: uses the store, key and ttl config values to store the schema as a string in the given cache store. + * - 2: uses the path config value to store the schema in a PHP file allowing OPcache to pick it up. + */ + 'version' => env('LIGHTHOUSE_CACHE_VERSION', 1), + + /* + * Allows using a specific cache store, uses the app's default if set to null. + * Only relevant if version is set to 1. + */ + 'store' => env('LIGHTHOUSE_CACHE_STORE', null), + + /* + * The name of the cache item for the schema cache. + * Only relevant if version is set to 1. + */ + 'key' => env('LIGHTHOUSE_CACHE_KEY', 'lighthouse-schema'), + + /* + * Duration in seconds the schema should remain cached, null means forever. + * Only relevant if version is set to 1. + */ + 'ttl' => env('LIGHTHOUSE_CACHE_TTL', null), + + /* + * File path to store the lighthouse schema. + * Only relevant if version is set to 2. + */ + 'path' => env('LIGHTHOUSE_CACHE_PATH', base_path('bootstrap/cache/lighthouse-schema.php')), + + /* + * Should the `@cache` directive use a tagged cache? + */ + 'tags' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Query Cache + |-------------------------------------------------------------------------- + | + | Caches the result of parsing incoming query strings to boost performance on subsequent requests. + | + */ + + 'query_cache' => [ + /* + * Setting to true enables query caching. + */ + 'enable' => env('LIGHTHOUSE_QUERY_CACHE_ENABLE', true), + + /* + * Allows using a specific cache store, uses the app's default if set to null. + */ + 'store' => env('LIGHTHOUSE_QUERY_CACHE_STORE', null), + + /* + * Duration in seconds (minutes for Laravel pre-5.8) the query should remain cached, null means forever. + */ + 'ttl' => env( + 'LIGHTHOUSE_QUERY_CACHE_TTL', + \Nuwave\Lighthouse\Support\AppVersion::atLeast(5.8) + ? 24 * 60 * 60 // 1 day in seconds + : 24 * 60 // 1 day in minutes + ), + ], + + /* + |-------------------------------------------------------------------------- + | Namespaces + |-------------------------------------------------------------------------- + | + | These are the default namespaces where Lighthouse looks for classes to + | extend functionality of the schema. You may pass in either a string + | or an array, they are tried in order and the first match is used. + | + */ + + 'namespaces' => [ + 'models' => ['App', 'App\\Models'], + 'queries' => 'App\\GraphQL\\Queries', + 'mutations' => 'App\\GraphQL\\Mutations', + 'subscriptions' => 'App\\GraphQL\\Subscriptions', + 'interfaces' => 'App\\GraphQL\\Interfaces', + 'unions' => 'App\\GraphQL\\Unions', + 'scalars' => 'App\\GraphQL\\Scalars', + 'directives' => ['App\\GraphQL\\Directives'], + 'validators' => ['App\\GraphQL\\Validators'], + ], + + /* + |-------------------------------------------------------------------------- + | Security + |-------------------------------------------------------------------------- + | + | Control how Lighthouse handles security related query validation. + | Read more at https://webonyx.github.io/graphql-php/security/ + | + */ + + 'security' => [ + 'max_query_complexity' => \GraphQL\Validator\Rules\QueryComplexity::DISABLED, + 'max_query_depth' => \GraphQL\Validator\Rules\QueryDepth::DISABLED, + 'disable_introspection' => (bool) env('LIGHTHOUSE_SECURITY_DISABLE_INTROSPECTION', false) + ? \GraphQL\Validator\Rules\DisableIntrospection::ENABLED + : \GraphQL\Validator\Rules\DisableIntrospection::DISABLED, + ], + + /* + |-------------------------------------------------------------------------- + | Pagination + |-------------------------------------------------------------------------- + | + | Set defaults for the pagination features within Lighthouse, such as + | the @paginate directive, or paginated relation directives. + | + */ + + 'pagination' => [ + /* + * Allow clients to query paginated lists without specifying the amount of items. + * Setting this to `null` means clients have to explicitly ask for the count. + */ + 'default_count' => null, + + /* + * Limit the maximum amount of items that clients can request from paginated lists. + * Setting this to `null` means the count is unrestricted. + */ + 'max_count' => null, + ], + + /* + |-------------------------------------------------------------------------- + | Debug + |-------------------------------------------------------------------------- + | + | Control the debug level as described in https://webonyx.github.io/graphql-php/error-handling/ + | Debugging is only applied if the global Laravel debug config is set to true. + | + | When you set this value through an environment variable, use the following reference table: + | 0 => INCLUDE_NONE + | 1 => INCLUDE_DEBUG_MESSAGE + | 2 => INCLUDE_TRACE + | 3 => INCLUDE_TRACE | INCLUDE_DEBUG_MESSAGE + | 4 => RETHROW_INTERNAL_EXCEPTIONS + | 5 => RETHROW_INTERNAL_EXCEPTIONS | INCLUDE_DEBUG_MESSAGE + | 6 => RETHROW_INTERNAL_EXCEPTIONS | INCLUDE_TRACE + | 7 => RETHROW_INTERNAL_EXCEPTIONS | INCLUDE_TRACE | INCLUDE_DEBUG_MESSAGE + | 8 => RETHROW_UNSAFE_EXCEPTIONS + | 9 => RETHROW_UNSAFE_EXCEPTIONS | INCLUDE_DEBUG_MESSAGE + | 10 => RETHROW_UNSAFE_EXCEPTIONS | INCLUDE_TRACE + | 11 => RETHROW_UNSAFE_EXCEPTIONS | INCLUDE_TRACE | INCLUDE_DEBUG_MESSAGE + | 12 => RETHROW_UNSAFE_EXCEPTIONS | RETHROW_INTERNAL_EXCEPTIONS + | 13 => RETHROW_UNSAFE_EXCEPTIONS | RETHROW_INTERNAL_EXCEPTIONS | INCLUDE_DEBUG_MESSAGE + | 14 => RETHROW_UNSAFE_EXCEPTIONS | RETHROW_INTERNAL_EXCEPTIONS | INCLUDE_TRACE + | 15 => RETHROW_UNSAFE_EXCEPTIONS | RETHROW_INTERNAL_EXCEPTIONS | INCLUDE_TRACE | INCLUDE_DEBUG_MESSAGE + | + */ + + 'debug' => env('LIGHTHOUSE_DEBUG', \GraphQL\Error\DebugFlag::INCLUDE_DEBUG_MESSAGE | \GraphQL\Error\DebugFlag::INCLUDE_TRACE), + + /* + |-------------------------------------------------------------------------- + | Error Handlers + |-------------------------------------------------------------------------- + | + | Register error handlers that receive the Errors that occur during execution + | and handle them. You may use this to log, filter or format the errors. + | The classes must implement \Nuwave\Lighthouse\Execution\ErrorHandler + | + */ + + 'error_handlers' => [ + \Nuwave\Lighthouse\Execution\AuthenticationErrorHandler::class, + \Nuwave\Lighthouse\Execution\AuthorizationErrorHandler::class, + \Nuwave\Lighthouse\Execution\ValidationErrorHandler::class, + \Nuwave\Lighthouse\Execution\ExtensionErrorHandler::class, + \Nuwave\Lighthouse\Execution\ReportingErrorHandler::class, + ], + + /* + |-------------------------------------------------------------------------- + | Field Middleware + |-------------------------------------------------------------------------- + | + | Register global field middleware directives that wrap around every field. + | Execution happens in the defined order, before other field middleware. + | The classes must implement \Nuwave\Lighthouse\Support\Contracts\FieldMiddleware + | + */ + + 'field_middleware' => [ + \Nuwave\Lighthouse\Schema\Directives\TrimDirective::class, + \Nuwave\Lighthouse\Schema\Directives\ConvertEmptyStringsToNullDirective::class, + \Nuwave\Lighthouse\Schema\Directives\SanitizeDirective::class, + \Nuwave\Lighthouse\Validation\ValidateDirective::class, + \Nuwave\Lighthouse\Schema\Directives\TransformArgsDirective::class, + \Nuwave\Lighthouse\Schema\Directives\SpreadDirective::class, + \Nuwave\Lighthouse\Schema\Directives\RenameArgsDirective::class, + \Nuwave\Lighthouse\Schema\Directives\DropArgsDirective::class, + ], + + /* + |-------------------------------------------------------------------------- + | Global ID + |-------------------------------------------------------------------------- + | + | The name that is used for the global id field on the Node interface. + | When creating a Relay compliant server, this must be named "id". + | + */ + + 'global_id_field' => 'id', + + /* + |-------------------------------------------------------------------------- + | Persisted Queries + |-------------------------------------------------------------------------- + | + | Lighthouse supports Automatic Persisted Queries (APQ), compatible with the + | [Apollo implementation](https://www.apollographql.com/docs/apollo-server/performance/apq). + | You may set this flag to either process or deny these queries. + | + */ + + 'persisted_queries' => true, + + /* + |-------------------------------------------------------------------------- + | Transactional Mutations + |-------------------------------------------------------------------------- + | + | If set to true, built-in directives that mutate models will be + | wrapped in a transaction to ensure atomicity. + | + */ + + 'transactional_mutations' => true, + + /* + |-------------------------------------------------------------------------- + | Mass Assignment Protection + |-------------------------------------------------------------------------- + | + | If set to true, mutations will use forceFill() over fill() when populating + | a model with arguments in mutation directives. Since GraphQL constrains + | allowed inputs by design, mass assignment protection is not needed. + | + */ + + 'force_fill' => true, + + /* + |-------------------------------------------------------------------------- + | Batchload Relations + |-------------------------------------------------------------------------- + | + | If set to true, relations marked with directives like @hasMany or @belongsTo + | will be optimized by combining the queries through the BatchLoader. + | + */ + + 'batchload_relations' => true, + + /* + |-------------------------------------------------------------------------- + | Shortcut Foreign Key Selection + |-------------------------------------------------------------------------- + | + | If set to true, Lighthouse will shortcut queries where the client selects only the + | foreign key pointing to a related model. Only works if the related model's primary + | key field is called exactly `id` for every type in your schema. + | + */ + + 'shortcut_foreign_key_selection' => false, + + /* + |-------------------------------------------------------------------------- + | Non-Null Pagination Results + |-------------------------------------------------------------------------- + | + | If set to true, the generated result type of paginated lists will be marked + | as non-nullable. This is generally more convenient for clients, but will + | cause validation errors to bubble further up in the result. + | + | This setting will be removed and always behave as if it were true in v6. + | + */ + + 'non_null_pagination_results' => false, + + /* + |-------------------------------------------------------------------------- + | Unbox BenSampo\Enum\Enum instances + |-------------------------------------------------------------------------- + | + | If set to true, Lighthouse will extract the internal $value from instances of + | BenSampo\Enum\Enum before passing it to ArgBuilderDirective::handleBuilder(). + | + | This setting will be removed and always behave as if it were false in v6. + | + | It is only here to preserve compatibility, e.g. when expecting the internal + | value to be passed to a scope when using @scope, but not needed due to Laravel + | calling the Enum's __toString() method automagically when used in a query. + | + */ + + 'unbox_bensampo_enum_enum_instances' => true, + + /* + |-------------------------------------------------------------------------- + | GraphQL Subscriptions + |-------------------------------------------------------------------------- + | + | Here you can define GraphQL subscription broadcaster and storage drivers + | as well their required configuration options. + | + */ + + 'subscriptions' => [ + /* + * Determines if broadcasts should be queued by default. + */ + 'queue_broadcasts' => env('LIGHTHOUSE_QUEUE_BROADCASTS', true), + + /* + * Determines the queue to use for broadcasting queue jobs. + */ + 'broadcasts_queue_name' => env('LIGHTHOUSE_BROADCASTS_QUEUE_NAME', null), + + /* + * Default subscription storage. + * + * Any Laravel supported cache driver options are available here. + */ + 'storage' => env('LIGHTHOUSE_SUBSCRIPTION_STORAGE', 'redis'), + + /* + * Default subscription storage time to live in seconds. + * + * Indicates how long a subscription can be active before it's automatically removed 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. + */ + 'storage_ttl' => env('LIGHTHOUSE_SUBSCRIPTION_STORAGE_TTL', null), + + /* + * Default subscription broadcaster. + */ + 'broadcaster' => env('LIGHTHOUSE_BROADCASTER', 'pusher'), + + /* + * Subscription broadcasting drivers with config options. + */ + 'broadcasters' => [ + 'log' => [ + 'driver' => 'log', + ], + 'pusher' => [ + 'driver' => 'pusher', + 'routes' => \Nuwave\Lighthouse\Subscriptions\SubscriptionRouter::class . '@pusher', + 'connection' => 'pusher', + ], + 'echo' => [ + 'driver' => 'echo', + 'connection' => env('LIGHTHOUSE_SUBSCRIPTION_REDIS_CONNECTION', 'default'), + 'routes' => \Nuwave\Lighthouse\Subscriptions\SubscriptionRouter::class . '@echoRoutes', + ], + ], + + /* + * Controls the format of the extensions response. + * Allowed values: 1, 2 + */ + 'version' => env('LIGHTHOUSE_SUBSCRIPTION_VERSION', 1), + + /* + * 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. + * Will default to true in v6 and be removed in v7. + */ + 'exclude_empty' => env('LIGHTHOUSE_SUBSCRIPTION_EXCLUDE_EMPTY', false), + ], + + /* + |-------------------------------------------------------------------------- + | Defer + |-------------------------------------------------------------------------- + | + | Configuration for the experimental @defer directive support. + | + */ + + 'defer' => [ + /* + * Maximum number of nested fields that can be deferred in one query. + * Once reached, remaining fields will be resolved synchronously. + * 0 means unlimited. + */ + 'max_nested_fields' => 0, + + /* + * Maximum execution time for deferred queries in milliseconds. + * Once reached, remaining fields will be resolved synchronously. + * 0 means unlimited. + */ + 'max_execution_ms' => 0, + ], + + /* + |-------------------------------------------------------------------------- + | Apollo Federation + |-------------------------------------------------------------------------- + | + | Lighthouse can act as a federated service: https://www.apollographql.com/docs/federation/federation-spec. + | + */ + + 'federation' => [ + /* + * Location of resolver classes when resolving the `_entities` field. + */ + 'entities_resolver_namespace' => 'App\\GraphQL\\Entities', + ], +]; diff --git a/config/sanctum.php b/config/sanctum.php index 529cfdc..6edfadd 100755 --- a/config/sanctum.php +++ b/config/sanctum.php @@ -54,7 +54,7 @@ |-------------------------------------------------------------------------- | | When authenticating your first-party SPA with Sanctum you may need to - | customize some of the middleware Sanctum uses while processing the + | customize some middleware Sanctum uses while processing the | request. You may change the middleware listed below as required. | */ diff --git a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php index 6c81fd2..f5730b1 100755 --- a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php +++ b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php @@ -11,7 +11,7 @@ * * @return void */ - public function up() + public function up(): void { Schema::create('personal_access_tokens', function (Blueprint $table) { $table->id(); @@ -30,7 +30,7 @@ public function up() * * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('personal_access_tokens'); } diff --git a/graphql/schema.graphql b/graphql/schema.graphql new file mode 100644 index 0000000..d0762bd --- /dev/null +++ b/graphql/schema.graphql @@ -0,0 +1,41 @@ +"A datetime string with format `Y-m-d H:i:s`, e.g. `2018-05-23 13:43:32`." +scalar DateTime @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\DateTime") + +"Indicates what fields are available at the top level of a query operation." +type Query { + "Find a single user by an identifying attribute." + user( + "Search by primary key." + id: ID @eq @rules(apply: ["prohibits:email", "required_without:email"]) + + "Search by email address." + email: String @eq @rules(apply: ["prohibits:id", "required_without:id", "email"]) + ): User @find + + "List multiple users." + users( + "Filters by name. Accepts SQL LIKE wildcards `%` and `_`." + name: String @where(operator: "like") + ): [User!]! @paginate(defaultCount: 10) +} + +"Account of a person who utilizes this application." +type User { + "Unique primary key." + id: ID! + + "Non-unique name." + name: String! + + "Unique email address." + email: String! + + "When the email was verified." + email_verified_at: DateTime + + "When the account was created." + created_at: DateTime! + + "When the account was last updated." + updated_at: DateTime! +} diff --git a/phpunit.xml b/phpunit.xml index 69168d3..d12ee76 100755 --- a/phpunit.xml +++ b/phpunit.xml @@ -21,7 +21,6 @@ - diff --git a/programmatic-types.graphql b/programmatic-types.graphql new file mode 100644 index 0000000..563982d --- /dev/null +++ b/programmatic-types.graphql @@ -0,0 +1,380 @@ +# File generated by "php artisan lighthouse:ide-helper". +# Do not edit this file directly. +# This file should be ignored by git as it can be autogenerated. + +""" +The `ID` scalar type represents a unique identifier, often used to +refetch an object or as key for a cache. The ID type appears in a JSON +response as a String; however, it is not intended to be human-readable. +When expected as an input type, any string (such as `"4"`) or integer +(such as `4`) input value will be accepted as an ID. +""" +scalar ID + +""" +The `String` scalar type represents textual data, represented as UTF-8 +character sequences. The String type is most often used by GraphQL to +represent free-form human-readable text. +""" +scalar String + +""" +The `Int` scalar type represents non-fractional signed whole numeric +values. Int can represent values between -(2^31) and 2^31 - 1. +""" +scalar Int + +"""A paginated list of User items.""" +type UserPaginator { + """Pagination information about the list of items.""" + paginatorInfo: PaginatorInfo! + + """A list of User items.""" + data: [User!]! +} + +"""Information about pagination using a fully featured paginator.""" +type PaginatorInfo { + """Number of items in the current page.""" + count: Int! + + """Index of the current page.""" + currentPage: Int! + + """Index of the first item in the current page.""" + firstItem: Int + + """Are there more pages after this one?""" + hasMorePages: Boolean! + + """Index of the last item in the current page.""" + lastItem: Int + + """Index of the last available page.""" + lastPage: Int! + + """Number of items per page.""" + perPage: Int! + + """Number of total available items.""" + total: Int! +} + +"""The `Boolean` scalar type represents `true` or `false`.""" +scalar Boolean + +""" +The `Float` scalar type represents signed double-precision fractional +values as specified by +[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). +""" +scalar Float + +""" +A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all +available types and directives on the server, as well as the entry points for +query, mutation, and subscription operations. +""" +type __Schema { + """A list of all types supported by this server.""" + types: [__Type!]! + + """The type that query operations will be rooted at.""" + queryType: __Type! + + """ + If this server supports mutation, the type that mutation operations will be rooted at. + """ + mutationType: __Type + + """ + If this server support subscription, the type that subscription operations will be rooted at. + """ + subscriptionType: __Type + + """A list of all directives supported by this server.""" + directives: [__Directive!]! +} + +""" +The fundamental unit of any GraphQL Schema is the type. There are many kinds of +types in GraphQL as represented by the `__TypeKind` enum. + +Depending on the kind of a type, certain fields describe information about that +type. Scalar types provide no information beyond a name and description, while +Enum types provide their values. Object and Interface types provide the fields +they describe. Abstract types, Union and Interface, provide the Object types +possible at runtime. List and NonNull types compose other types. +""" +type __Type { + kind: __TypeKind! + name: String + description: String + fields(includeDeprecated: Boolean = false): [__Field!] + interfaces: [__Type!] + possibleTypes: [__Type!] + enumValues(includeDeprecated: Boolean = false): [__EnumValue!] + inputFields: [__InputValue!] + ofType: __Type +} + +"""An enum describing what kind of type a given `__Type` is.""" +enum __TypeKind { + """Indicates this type is a scalar.""" + SCALAR + + """ + Indicates this type is an object. `fields` and `interfaces` are valid fields. + """ + OBJECT + + """ + Indicates this type is an interface. `fields`, `interfaces`, and `possibleTypes` are valid fields. + """ + INTERFACE + + """Indicates this type is a union. `possibleTypes` is a valid field.""" + UNION + + """Indicates this type is an enum. `enumValues` is a valid field.""" + ENUM + + """ + Indicates this type is an input object. `inputFields` is a valid field. + """ + INPUT_OBJECT + + """Indicates this type is a list. `ofType` is a valid field.""" + LIST + + """Indicates this type is a non-null. `ofType` is a valid field.""" + NON_NULL +} + +""" +Object and Interface types are described by a list of Fields, each of which has +a name, potentially a list of arguments, and a return type. +""" +type __Field { + name: String! + description: String + args: [__InputValue!]! + type: __Type! + isDeprecated: Boolean! + deprecationReason: String +} + +""" +Arguments provided to Fields or Directives and the input fields of an +InputObject are represented as Input Values which describe their type and +optionally a default value. +""" +type __InputValue { + name: String! + description: String + type: __Type! + + """ + A GraphQL-formatted string representing the default value for this input value. + """ + defaultValue: String +} + +""" +One possible value for a given Enum. Enum values are unique values, not a +placeholder for a string or numeric value. However an Enum value is returned in +a JSON response as a string. +""" +type __EnumValue { + name: String! + description: String + isDeprecated: Boolean! + deprecationReason: String +} + +""" +A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document. + +In some cases, you need to provide options to alter GraphQL's execution behavior +in ways field arguments will not suffice, such as conditionally including or +skipping a field. Directives provide this by describing additional information +to the executor. +""" +type __Directive { + name: String! + description: String + args: [__InputValue!]! + isRepeatable: Boolean! + locations: [__DirectiveLocation!]! +} + +""" +A Directive can be adjacent to many parts of the GraphQL language, a +__DirectiveLocation describes one such possible adjacencies. +""" +enum __DirectiveLocation { + """Location adjacent to a query operation.""" + QUERY + + """Location adjacent to a mutation operation.""" + MUTATION + + """Location adjacent to a subscription operation.""" + SUBSCRIPTION + + """Location adjacent to a field.""" + FIELD + + """Location adjacent to a fragment definition.""" + FRAGMENT_DEFINITION + + """Location adjacent to a fragment spread.""" + FRAGMENT_SPREAD + + """Location adjacent to an inline fragment.""" + INLINE_FRAGMENT + + """Location adjacent to a variable definition.""" + VARIABLE_DEFINITION + + """Location adjacent to a schema definition.""" + SCHEMA + + """Location adjacent to a scalar definition.""" + SCALAR + + """Location adjacent to an object type definition.""" + OBJECT + + """Location adjacent to a field definition.""" + FIELD_DEFINITION + + """Location adjacent to an argument definition.""" + ARGUMENT_DEFINITION + + """Location adjacent to an interface definition.""" + INTERFACE + + """Location adjacent to a union definition.""" + UNION + + """Location adjacent to an enum definition.""" + ENUM + + """Location adjacent to an enum value definition.""" + ENUM_VALUE + + """Location adjacent to an input object type definition.""" + INPUT_OBJECT + + """Location adjacent to an input object field definition.""" + INPUT_FIELD_DEFINITION +} + +"""Directions for ordering a list of records.""" +enum SortOrder { + """Sort records in ascending order.""" + ASC + + """Sort records in descending order.""" + DESC +} + +""" +Aggregate functions when ordering by a relation without specifying a column. +""" +enum OrderByRelationAggregateFunction { + """Amount of items.""" + COUNT +} + +""" +Aggregate functions when ordering by a relation that may specify a column. +""" +enum OrderByRelationWithColumnAggregateFunction { + """Average.""" + AVG + + """Minimum.""" + MIN + + """Maximum.""" + MAX + + """Sum.""" + SUM + + """Amount of items.""" + COUNT +} + +"""Allows ordering a list of records.""" +input OrderByClause { + """The column that is used for ordering.""" + column: String! + + """The direction that is used for ordering.""" + order: SortOrder! +} + +"""Information about pagination using a simple paginator.""" +type SimplePaginatorInfo { + """Number of items in the current page.""" + count: Int! + + """Index of the current page.""" + currentPage: Int! + + """Index of the first item in the current page.""" + firstItem: Int + + """Index of the last item in the current page.""" + lastItem: Int + + """Number of items per page.""" + perPage: Int! + + """Are there more pages after this one?""" + hasMorePages: Boolean! +} + +"""Information about pagination using a Relay style cursor connection.""" +type PageInfo { + """When paginating forwards, are there more items?""" + hasNextPage: Boolean! + + """When paginating backwards, are there more items?""" + hasPreviousPage: Boolean! + + """The cursor to continue paginating backwards.""" + startCursor: String + + """The cursor to continue paginating forwards.""" + endCursor: String + + """Total number of nodes in the paginated connection.""" + total: Int! + + """Number of nodes in the current page.""" + count: Int! + + """Index of the current page.""" + currentPage: Int! + + """Index of the last available page.""" + lastPage: Int! +} + +""" +Specify if you want to include or exclude trashed results from a query. +""" +enum Trashed { + """Only return trashed results.""" + ONLY + + """Return both trashed and non-trashed results.""" + WITH + + """Only return non-trashed results.""" + WITHOUT +} diff --git a/schema-directives.graphql b/schema-directives.graphql new file mode 100644 index 0000000..bee8557 --- /dev/null +++ b/schema-directives.graphql @@ -0,0 +1,1764 @@ +# File generated by "php artisan lighthouse:ide-helper". +# Do not edit this file directly. +# This file should be ignored by git as it can be autogenerated. + +""" +Placeholder type for various directives such as `@orderBy`. +Will be replaced by a generated type during schema manipulation. +""" +scalar _ + +# Directive class: Nuwave\Lighthouse\Testing\MockDirective +""" +Allows you to easily hook up a resolver for an endpoint. +""" +directive @mock( + """ + Specify a unique key for the mock resolver. + """ + key: String = "default" +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Auth\AuthDirective +""" +Return the currently authenticated user as the result of a query. +""" +directive @auth( + """ + Specify which guard to use, e.g. "api". + When not defined, the default from `lighthouse.php` is used. + """ + guard: String +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Auth\CanDirective +""" +Check a Laravel Policy to ensure the current user is authorized to access a field. + +When `injectArgs` and `args` are used together, the client given +arguments will be passed before the static args. +""" +directive @can( + """ + The ability to check permissions for. + """ + ability: String! + + """ + Check the policy against the model instances returned by the field resolver. + Only use this if the field does not mutate data, it is run before checking. + + Mutually exclusive with `query` and `find`. + """ + resolved: Boolean! = false + + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String + + """ + Pass along the client given input data as arguments to `Gate::check`. + """ + injectArgs: Boolean! = false + + """ + Statically defined arguments that are passed to `Gate::check`. + + You may pass arbitrary GraphQL literals, + e.g.: [1, 2, 3] or { foo: "bar" } + """ + args: CanArgs + + """ + Query for specific model instances to check the policy against, using arguments + with directives that add constraints to the query builder, such as `@eq`. + + Mutually exclusive with `resolved` and `find`. + """ + query: Boolean! = false + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + If your policy checks against specific model instances, specify + the name of the field argument that contains its primary key(s). + + You may pass the string in dot notation to use nested inputs. + + Mutually exclusive with `resolved` and `query`. + """ + find: String +) repeatable on FIELD_DEFINITION + +""" +Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-Input-Values +""" +scalar CanArgs + +# Directive class: Nuwave\Lighthouse\Auth\GuardDirective +""" +Run authentication through one or more guards. + +This is run per field and may allow unauthenticated +users to still receive partial results. + +Used upon an object, it applies to all fields within. +""" +directive @guard( + """ + Specify which guards to use, e.g. ["web"]. + When not defined, the default from `lighthouse.php` is used. + """ + with: [String!] +) repeatable on FIELD_DEFINITION | OBJECT + +# Directive class: Nuwave\Lighthouse\Auth\WhereAuthDirective +""" +Filter a type to only return instances owned by the current user. +""" +directive @whereAuth( + """ + Name of the relationship that links to the user model. + """ + relation: String! + + """ + Specify which guard to use, e.g. "api". + When not defined, the default from `lighthouse.php` is used. + """ + guard: String +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Cache\CacheDirective +""" +Cache the result of a resolver. +""" +directive @cache( + """ + Set the duration it takes for the cache to expire in seconds. + If not given, the result will be stored forever. + """ + maxAge: Int + + """ + Limit access to cached data to the currently authenticated user. + When the field is accessible by guest users, this will not have + any effect, they will access a shared cache. + """ + private: Boolean = false +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Cache\CacheKeyDirective +""" +Specify the field to use as a key when creating a cache. +""" +directive @cacheKey on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Cache\ClearCacheDirective +""" +Clear a resolver cache by tags. +""" +directive @clearCache( + """ + Name of the parent type of the field to clear. + """ + type: String! + + """ + Source of the parent ID to clear. + """ + idSource: ClearCacheIdSource + + """ + Name of the field to clear. + """ + field: String +) repeatable on FIELD_DEFINITION + +""" +Options for the `id` argument on `@clearCache`. + +Exactly one of the fields must be given. +""" +input ClearCacheIdSource { + """ + Path of an argument the client passes to the field `@clearCache` is applied to. + """ + argument: String + + """ + Path of a field in the result returned from the field `@clearCache` is applied to. + """ + field: String +} + +# Directive class: Nuwave\Lighthouse\GlobalId\GlobalIdDirective +""" +Converts between IDs/types and global IDs. + +When used upon a field, it encodes; +when used upon an argument, it decodes. +""" +directive @globalId( + """ + Decoding a global id produces a tuple of `$type` and `$id`. + This setting controls which of those is passed along. + """ + decode: GlobalIdDecode = ARRAY +) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION + +""" +Options for the `decode` argument of `@globalId`. +""" +enum GlobalIdDecode { + """ + Return an array of `[$type, $id]`. + """ + ARRAY + + """ + Return just `$type`. + """ + TYPE + + """ + Return just `$id`. + """ + ID +} + +# Directive class: Nuwave\Lighthouse\GlobalId\NodeDirective +""" +Register a type for Relay's global object identification. + +When used without any arguments, Lighthouse will attempt +to resolve the type through a model with the same name. +""" +directive @node( + """ + Reference to a function that receives the decoded `id` and returns a result. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + + Mutually exclusive with `model`. + """ + resolver: String + + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + + Mutually exclusive with `resolver`. + """ + model: String +) on OBJECT + +# Directive class: Nuwave\Lighthouse\OrderBy\OrderByDirective +""" +Sort a result list by one or more given columns. +""" +directive @orderBy( + """ + Restrict the allowed column names to a well-defined list. + This improves introspection capabilities and security. + Mutually exclusive with `columnsEnum`. + Only used when the directive is added on an argument. + """ + columns: [String!] + + """ + Use an existing enumeration type to restrict the allowed columns to a predefined list. + This allows you to re-use the same enum for multiple fields. + Mutually exclusive with `columns`. + Only used when the directive is added on an argument. + """ + columnsEnum: String + + """ + Allow clients to sort by aggregates on relations. + Only used when the directive is added on an argument. + """ + relations: [OrderByRelation!] + + """ + The database column for which the order by clause will be applied on. + Only used when the directive is added on a field. + """ + column: String + + """ + The direction of the order by clause. + Only used when the directive is added on a field. + """ + direction: OrderByDirection = ASC +) on ARGUMENT_DEFINITION | FIELD_DEFINITION + +""" +Options for the `direction` argument on `@orderBy`. +""" +enum OrderByDirection { + """ + Sort in ascending order. + """ + ASC + + """ + Sort in descending order. + """ + DESC +} + +""" +Options for the `relations` argument on `@orderBy`. +""" +input OrderByRelation { + """ + Name of the relation. + """ + relation: String! + + """ + Restrict the allowed column names to a well-defined list. + This improves introspection capabilities and security. + Mutually exclusive with `columnsEnum`. + """ + columns: [String!] + + """ + Use an existing enumeration type to restrict the allowed columns to a predefined list. + This allows you to re-use the same enum for multiple fields. + Mutually exclusive with `columns`. + """ + columnsEnum: String +} + +# Directive class: Nuwave\Lighthouse\Pagination\PaginateDirective +""" +Query multiple entries as a paginated list. +""" +directive @paginate( + """ + Which pagination style should be used. + """ + type: PaginateType = PAGINATOR + + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + Mutually exclusive with `builder` and `resolver`. + """ + model: String + + """ + Point to a function that provides a Query Builder instance. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + Mutually exclusive with `model` and `resolver`. + """ + builder: String + + """ + Reference a function that resolves the field by directly returning data in a Paginator instance. + Mutually exclusive with `builder` and `model`. + Not compatible with `scopes` and builder arguments such as `@eq`. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + """ + resolver: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + Allow clients to query paginated lists without specifying the amount of items. + Overrules the `pagination.default_count` setting from `lighthouse.php`. + Setting this to `null` means clients have to explicitly ask for the count. + """ + defaultCount: Int + + """ + Limit the maximum amount of items that clients can request from paginated lists. + Overrules the `pagination.max_count` setting from `lighthouse.php`. + Setting this to `null` means the count is unrestricted. + """ + maxCount: Int +) on FIELD_DEFINITION + +""" +Options for the `type` argument of `@paginate`. +""" +enum PaginateType { + """ + Offset-based pagination, similar to the Laravel default. + """ + PAGINATOR + + """ + Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + """ + SIMPLE + + """ + Cursor-based pagination, compatible with the Relay specification. + """ + CONNECTION +} + +# Directive class: Nuwave\Lighthouse\Scout\SearchDirective +""" +Perform a full-text search by the given input value. +""" +directive @search( + """ + Specify a custom index to use for search. + """ + within: String +) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\SoftDeletes\ForceDeleteDirective +""" +Permanently remove one or more soft deleted models by their ID. +The field must have a single non-null argument that may be a list. +""" +directive @forceDelete( + """ + DEPRECATED use @globalId, will be removed in v6 + + Set to `true` to use global ids for finding the model. + If set to `false`, regular non-global ids are used. + """ + globalId: Boolean = false + + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\SoftDeletes\RestoreDirective +""" +Un-delete one or more soft deleted models by their ID. +The field must have a single non-null argument that may be a list. +""" +directive @restore( + """ + DEPRECATED use @globalId, will be removed in v6 + + Set to `true` to use global ids for finding the model. + If set to `false`, regular non-global ids are used. + """ + globalId: Boolean = false + + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\SoftDeletes\SoftDeletesDirective +""" +Allows to filter if trashed elements should be fetched. +This manipulates the schema by adding the argument +`trashed: Trashed @trashed` to the field. +""" +directive @softDeletes on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\SoftDeletes\TrashedDirective +""" +Allows to filter if trashed elements should be fetched. +""" +directive @trashed on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Validation\RulesDirective +""" +Validate an argument using [Laravel validation](https://laravel.com/docs/validation). +""" +directive @rules( + """ + Specify the validation rules to apply to the field. + This can either be a reference to [Laravel's built-in validation rules](https://laravel.com/docs/validation#available-validation-rules), + or the fully qualified class name of a custom validation rule. + + Rules that mutate the incoming arguments, such as `exclude_if`, are not supported + by Lighthouse. Use ArgTransformerDirectives or FieldMiddlewareDirectives instead. + """ + apply: [String!]! + + """ + Specify a custom attribute name to use in your validation message. + """ + attribute: String + + """ + Specify the messages to return if the validators fail. + """ + messages: [RulesMessage!] +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +""" +Input for the `messages` argument of `@rules`. +""" +input RulesMessage { + """ + Name of the rule, e.g. `"email"`. + """ + rule: String! + + """ + Message to display if the rule fails, e.g. `"Must be a valid email"`. + """ + message: String! +} + +# Directive class: Nuwave\Lighthouse\Validation\RulesForArrayDirective +""" +Run validation on an array itself, using [Laravel built-in validation](https://laravel.com/docs/validation). +""" +directive @rulesForArray( + """ + Specify the validation rules to apply to the field. + This can either be a reference to any of Laravel's built-in validation rules: https://laravel.com/docs/validation#available-validation-rules, + or the fully qualified class name of a custom validation rule. + """ + apply: [String!]! + + """ + Specify a custom attribute name to use in your validation message. + """ + attribute: String + + """ + Specify the messages to return if the validators fail. + """ + messages: [RulesForArrayMessage!] +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +""" +Input for the `messages` argument of `@rulesForArray`. +""" +input RulesForArrayMessage { + """ + Name of the rule, e.g. `"email"`. + """ + rule: String! + + """ + Message to display if the rule fails, e.g. `"Must be a valid email"`. + """ + message: String! +} + +# Directive class: Nuwave\Lighthouse\Validation\ValidateDirective +""" +Run validation on a field. +""" +directive @validate on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Validation\ValidatorDirective +""" +Provide validation rules through a PHP class. +""" +directive @validator( + """ + The name of the class to use. + + If defined on an input, this defaults to a class called `{$inputName}Validator` in the + default validator namespace. For fields, it uses the namespace of the parent type + and the field name: `{$parent}\{$field}Validator`. + """ + class: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION | INPUT_OBJECT + +# Directive class: Nuwave\Lighthouse\Schema\Directives\AggregateDirective +""" +Returns an aggregate of a column in a given relationship or model. + +Requires Laravel 8+. +""" +directive @aggregate( + """ + The column to aggregate. + """ + column: String! + + """ + The aggregate function to compute. + """ + function: AggregateFunction! + + """ + The relationship with the column to aggregate. + Mutually exclusive with `model` and `builder`. + """ + relation: String + + """ + The model with the column to aggregate. + Mutually exclusive with `relation` and `builder`. + """ + model: String + + """ + Point to a function that provides a Query Builder instance. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + Mutually exclusive with `relation` and `model`. + """ + builder: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +""" +Options for the `function` argument of `@aggregate`. +""" +enum AggregateFunction { + """ + Return the average value. + """ + AVG + + """ + Return the sum. + """ + SUM + + """ + Return the minimum. + """ + MIN + + """ + Return the maximum. + """ + MAX +} + +# Directive class: Nuwave\Lighthouse\Schema\Directives\AllDirective +""" +Fetch all Eloquent models and return the collection as the result. +""" +directive @all( + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + Mutually exclusive with `builder`. + """ + model: String + + """ + Point to a function that provides a Query Builder instance. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + Mutually exclusive with `model`. + """ + builder: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\BelongsToDirective +""" +Resolves a field through the Eloquent `BelongsTo` relationship. +""" +directive @belongsTo( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\BelongsToManyDirective +""" +Resolves a field through the Eloquent `BelongsToMany` relationship. +""" +directive @belongsToMany( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + Allows to resolve the relation as a paginated list. + """ + type: BelongsToManyType + + """ + Allow clients to query paginated lists without specifying the amount of items. + Overrules the `pagination.default_count` setting from `lighthouse.php`. + Setting this to `null` means clients have to explicitly ask for the count. + """ + defaultCount: Int + + """ + Limit the maximum amount of items that clients can request from paginated lists. + Overrules the `pagination.max_count` setting from `lighthouse.php`. + Setting this to `null` means the count is unrestricted. + """ + maxCount: Int + + """ + Specify a custom type that implements the Edge interface + to extend edge object. + Only applies when using Relay style "connection" pagination. + """ + edgeType: String +) on FIELD_DEFINITION + +""" +Options for the `type` argument of `@belongsToMany`. +""" +enum BelongsToManyType { + """ + Offset-based pagination, similar to the Laravel default. + """ + PAGINATOR + + """ + Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + """ + SIMPLE + + """ + Cursor-based pagination, compatible with the Relay specification. + """ + CONNECTION +} + +# Directive class: Nuwave\Lighthouse\Schema\Directives\BuilderDirective +""" +Manipulate the query builder with a method. +""" +directive @builder( + """ + Reference a method that is passed the query builder. + Consists of two parts: a class name and a method name, separated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + """ + method: String! + + """ + Pass a value to the method as the second argument after the query builder. + Only used when the directive is added on a field. + """ + value: BuilderValue +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION + +""" +Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-Input-Values +""" +scalar BuilderValue + +# Directive class: Nuwave\Lighthouse\Schema\Directives\ComplexityDirective +""" +Customize the calculation of a fields complexity score before execution. +""" +directive @complexity( + """ + Reference a function to customize the complexity score calculation. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + """ + resolver: String +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\ConvertEmptyStringsToNullDirective +""" +Replaces `""` with `null`. +""" +directive @convertEmptyStringsToNull on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\CountDirective +""" +Returns the count of a given relationship or model. +""" +directive @count( + """ + The relationship to count. + Mutually exclusive with `model`. + """ + relation: String + + """ + The model to count. + Mutually exclusive with `relation`. + """ + model: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + Count only rows where the given columns are non-null. + `*` counts every row. + """ + columns: [String!]! = ["*"] + + """ + Should exclude duplicated rows? + """ + distinct: Boolean! = false +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\CreateDirective +""" +Create a new Eloquent model with the given arguments. +""" +directive @create( + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String + + """ + Specify the name of the relation on the parent model. + This is only needed when using this directive as a nested arg + resolver and if the name of the relation is not the arg name. + """ + relation: String +) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\DeleteDirective +""" +Delete one or more models by their ID. +The field must have a single non-null argument that may be a list. +""" +directive @delete( + """ + DEPRECATED use @globalId, will be removed in v6 + + Set to `true` to use global ids for finding the model. + If set to `false`, regular non-global ids are used. + """ + globalId: Boolean = false + + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String + + """ + Specify the name of the relation on the parent model. + This is only needed when using this directive as a nested arg + resolver and if the name of the relation is not the arg name. + """ + relation: String +) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\DeprecatedDirective +""" +Marks an element of a GraphQL schema as no longer supported. +""" +directive @deprecated( + """ + Explains why this element was deprecated, usually also including a + suggestion for how to access supported similar data. Formatted + in [Markdown](https://daringfireball.net/projects/markdown). + """ + reason: String = "No longer supported" +) on FIELD_DEFINITION | ENUM_VALUE + +# Directive class: Nuwave\Lighthouse\Schema\Directives\DropArgsDirective +""" +Apply the @drop directives on the incoming arguments. +""" +directive @dropArgs on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\DropDirective +""" +Ignore the user given value, don't pass it to the resolver. +""" +directive @drop on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\EnumDirective +""" +Assign an internal 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. +""" +directive @enum( + """ + The internal value of the enum key. + """ + value: EnumValue +) on ENUM_VALUE + +""" +Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-Input-Values +""" +scalar EnumValue + +# Directive class: Nuwave\Lighthouse\Schema\Directives\EqDirective +""" +Add an equal conditional to a database query. +""" +directive @eq( + """ + Specify the database column to compare. + Required if the directive is: + - used on an argument and the database column has a different name + - used on a field + """ + key: String + + """ + Provide a value to compare against. + Only required when this directive is used on a field. + """ + value: EqValue +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION + +""" +Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-Input-Values +""" +scalar EqValue + +# Directive class: Nuwave\Lighthouse\Schema\Directives\EventDirective +""" +Dispatch an event after the resolution of a field. + +The event constructor will be called with a single argument: +the resolved value of the field. +""" +directive @event( + """ + Specify the fully qualified class name (FQCN) of the event to dispatch. + """ + dispatch: String! +) repeatable on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\FieldDirective +""" +Assign a resolver function to a field. +""" +directive @field( + """ + A reference to the resolver function to be used. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + """ + resolver: String! + + """ + Supply additional data to the resolver. + """ + args: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\FindDirective +""" +Find a model based on the arguments provided. +""" +directive @find( + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\FirstDirective +""" +Get the first query result from a collection of Eloquent models. +""" +directive @first( + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\HasManyDirective +""" +Corresponds to [the Eloquent relationship HasMany](https://laravel.com/docs/eloquent-relationships#one-to-many). +""" +directive @hasMany( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + Allows to resolve the relation as a paginated list. + Allowed values: `paginator`, `connection`. + """ + type: HasManyType + + """ + Allow clients to query paginated lists without specifying the amount of items. + Overrules the `pagination.default_count` setting from `lighthouse.php`. + Setting this to `null` means clients have to explicitly ask for the count. + """ + defaultCount: Int + + """ + Limit the maximum amount of items that clients can request from paginated lists. + Overrules the `pagination.max_count` setting from `lighthouse.php`. + Setting this to `null` means the count is unrestricted. + """ + maxCount: Int + + """ + Specify a custom type that implements the Edge interface + to extend edge object. + Only applies when using Relay style "connection" pagination. + """ + edgeType: String +) on FIELD_DEFINITION + +""" +Options for the `type` argument of `@hasMany`. +""" +enum HasManyType { + """ + Offset-based pagination, similar to the Laravel default. + """ + PAGINATOR + + """ + Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + """ + SIMPLE + + """ + Cursor-based pagination, compatible with the Relay specification. + """ + CONNECTION +} + +# Directive class: Nuwave\Lighthouse\Schema\Directives\HasManyThroughDirective +""" +Corresponds to [the Eloquent relationship HasManyThrough](https://laravel.com/docs/eloquent-relationships#has-many-through). +""" +directive @hasManyThrough( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + Allows to resolve the relation as a paginated list. + Allowed values: `paginator`, `connection`. + """ + type: HasManyThroughType + + """ + Allow clients to query paginated lists without specifying the amount of items. + Overrules the `pagination.default_count` setting from `lighthouse.php`. + """ + defaultCount: Int + + """ + Limit the maximum amount of items that clients can request from paginated lists. + Overrules the `pagination.max_count` setting from `lighthouse.php`. + """ + maxCount: Int + + """ + Specify a custom type that implements the Edge interface + to extend edge object. + Only applies when using Relay style "connection" pagination. + """ + edgeType: String +) on FIELD_DEFINITION + +""" +Options for the `type` argument of `@hasManyThrough`. +""" +enum HasManyThroughType { + """ + Offset-based pagination, similar to the Laravel default. + """ + PAGINATOR + + """ + Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + """ + SIMPLE + + """ + Cursor-based pagination, compatible with the Relay specification. + """ + CONNECTION +} + +# Directive class: Nuwave\Lighthouse\Schema\Directives\HasOneDirective +""" +Corresponds to [the Eloquent relationship HasOne](https://laravel.com/docs/eloquent-relationships#one-to-one). +""" +directive @hasOne( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\HashDirective +""" +Use Laravel hashing to transform an argument value. + +Useful for hashing passwords before inserting them into the database. +This uses the default hashing driver defined in `config/hashing.php`. +""" +directive @hash on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\InDirective +""" +Use the client given list value to add an IN conditional to a database query. +""" +directive @in( + """ + Specify the database column to compare. + Only required if database column has a different name than the attribute in your schema. + """ + key: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\InjectDirective +""" +Inject a value from the context object into the arguments. +""" +directive @inject( + """ + A path to the property of the context that will be injected. + If the value is nested within the context, you may use dot notation + to get it, e.g. "user.id". + """ + context: String! + + """ + The target name of the argument into which the value is injected. + You can use dot notation to set the value at arbitrary depth + within the incoming argument. + """ + name: String! +) repeatable on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\InterfaceDirective +""" +Use a custom resolver to determine the concrete type of an interface. +""" +directive @interface( + """ + Reference to a custom type-resolver function. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + """ + resolveType: String! +) on INTERFACE + +# Directive class: Nuwave\Lighthouse\Schema\Directives\LazyLoadDirective +""" +Perform a [lazy eager load](https://laravel.com/docs/eloquent-relationships#lazy-eager-loading) +on the relations of a list of models. +""" +directive @lazyLoad( + """ + The names of the relationship methods to load. + """ + relations: [String!]! +) repeatable on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\LikeDirective +""" +Add a `LIKE` conditional to a database query. +""" +directive @like( + """ + Specify the database column to compare. + Required if the directive is: + - used on an argument and the database column has a different name + - used on a field + """ + key: String + + """ + Fixate the positions of wildcards (`%`, `_`) in the LIKE comparison around the + placeholder `{}`, e.g. `%{}`, `__{}` or `%{}%`. + If specified, wildcard characters in the client-given input are escaped. + If not specified, the client can pass wildcards unescaped. + """ + template: String + + """ + Provide a value to compare against. + Only used when the directive is added on a field. + """ + value: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\LimitDirective +""" +Allow clients to specify the maximum number of results to return. +""" +directive @limit on ARGUMENT_DEFINITION | FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\MethodDirective +""" +Resolve a field by calling a method on the parent object. + +Use this if the data is not accessible through simple property access or if you +want to pass argument to the method. +""" +directive @method( + """ + Specify the method of which to fetch the data from. + Defaults to the name of the field if not given. + """ + name: String +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\ModelDirective +""" +Map a model class to an object type. + +This can be used when the name of the model differs from the name of the type. +""" +directive @model( + """ + The class name of the corresponding model. + """ + class: String! +) on OBJECT + +# Directive class: Nuwave\Lighthouse\Schema\Directives\MorphManyDirective +""" +Corresponds to [Eloquent's MorphMany-Relationship](https://laravel.com/docs/eloquent-relationships#one-to-many-polymorphic-relations). +""" +directive @morphMany( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + Allows to resolve the relation as a paginated list. + """ + type: MorphManyType + + """ + Allow clients to query paginated lists without specifying the amount of items. + Overrules the `pagination.default_count` setting from `lighthouse.php`. + Setting this to `null` means clients have to explicitly ask for the count. + """ + defaultCount: Int + + """ + Limit the maximum amount of items that clients can request from paginated lists. + Overrules the `pagination.max_count` setting from `lighthouse.php`. + Setting this to `null` means the count is unrestricted. + """ + maxCount: Int + + """ + Specify a custom type that implements the Edge interface + to extend edge object. + Only applies when using Relay style "connection" pagination. + """ + edgeType: String +) on FIELD_DEFINITION + +""" +Options for the `type` argument of `@morphMany`. +""" +enum MorphManyType { + """ + Offset-based pagination, similar to the Laravel default. + """ + PAGINATOR + + """ + Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + """ + SIMPLE + + """ + Cursor-based pagination, compatible with the Relay specification. + """ + CONNECTION +} + +# Directive class: Nuwave\Lighthouse\Schema\Directives\MorphOneDirective +""" +Corresponds to [Eloquent's MorphOne-Relationship](https://laravel.com/docs/eloquent-relationships#one-to-one-polymorphic-relations). +""" +directive @morphOne( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\MorphToDirective +""" +Corresponds to [Eloquent's MorphTo-Relationship](https://laravel.com/docs/eloquent-relationships#one-to-one-polymorphic-relations). +""" +directive @morphTo( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\MorphToManyDirective +""" +Corresponds to [Eloquent's ManyToMany-Polymorphic-Relationship](https://laravel.com/docs/eloquent-relationships#many-to-many-polymorphic-relations). +""" +directive @morphToMany( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] + + """ + Allows to resolve the relation as a paginated list. + """ + type: MorphToManyType + + """ + Allow clients to query paginated lists without specifying the amount of items. + Overrules the `pagination.default_count` setting from `lighthouse.php`. + Setting this to `null` means clients have to explicitly ask for the count. + """ + defaultCount: Int + + """ + Limit the maximum amount of items that clients can request from paginated lists. + Overrules the `pagination.max_count` setting from `lighthouse.php`. + Setting this to `null` means the count is unrestricted. + """ + maxCount: Int + + """ + Specify a custom type that implements the Edge interface + to extend edge object. + Only applies when using Relay style "connection" pagination. + """ + edgeType: String +) on FIELD_DEFINITION + +""" +Options for the `type` argument of `@morphToMany`. +""" +enum MorphToManyType { + """ + Offset-based pagination, similar to the Laravel default. + """ + PAGINATOR + + """ + Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records. + """ + SIMPLE + + """ + Cursor-based pagination, compatible with the Relay specification. + """ + CONNECTION +} + +# Directive class: Nuwave\Lighthouse\Schema\Directives\NamespaceDirective +""" +Redefine the default namespaces used in other directives. +The arguments are a map from directive names to namespaces. +""" +directive @namespace repeatable on FIELD_DEFINITION | OBJECT + +# Directive class: Nuwave\Lighthouse\Schema\Directives\NeqDirective +""" +Use the client given value to add an not-equal conditional to a database query. +""" +directive @neq( + """ + Specify the database column to compare. + Only required if database column has a different name than the attribute in your schema. + """ + key: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\NestDirective +""" +A no-op nested arg resolver that delegates all calls +to the ArgResolver directives attached to the children. +""" +directive @nest on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\NotInDirective +""" +Use the client given value to add a NOT IN conditional to a database query. +""" +directive @notIn( + """ + Specify the database column to compare. + Only required if database column has a different name than the attribute in your schema. + """ + key: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\RenameArgsDirective +""" +Apply the @rename directives on the incoming arguments. +""" +directive @renameArgs on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\RenameDirective +""" +Change the internally used name of a field or argument. + +This does not change the schema from a client perspective. +""" +directive @rename( + """ + The internal name of an attribute/property/key. + """ + attribute: String! +) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\SanitizeDirective +""" +Apply sanitization to the arguments of a field. +""" +directive @sanitize on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\ScalarDirective +""" +Reference a class implementing a scalar definition. +""" +directive @scalar( + """ + Reference to a class that extends `\GraphQL\Type\Definition\ScalarType`. + """ + class: String! +) on SCALAR + +# Directive class: Nuwave\Lighthouse\Schema\Directives\ScopeDirective +""" +Adds a scope to the query builder. + +The scope method will receive the client-given value of the argument as the second parameter. +""" +directive @scope( + """ + The name of the scope. + Defaults to the name of the argument. + """ + name: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\SpreadDirective +""" +Merge the fields of a nested input object into the arguments of its parent +when processing the field arguments given by a client. +""" +directive @spread on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\ThrottleDirective +""" +Sets rate limit to access the field. Does the same as ThrottleRequests Laravel Middleware. +""" +directive @throttle( + """ + Named preconfigured rate limiter. Requires Laravel 8.x or later. + """ + name: String + + """ + Maximum number of attempts in a specified time interval. + """ + maxAttempts: Int = 60 + + """ + Time in minutes to reset attempts. + """ + decayMinutes: Float = 1.0 + + """ + Prefix to distinguish several field groups. + """ + prefix: String +) on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\TransformArgsDirective +""" +Transform the arguments of a field. +""" +directive @transformArgs on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\TrimDirective +""" +Remove whitespace from the beginning and end of a given input. + +This can be used on: +- a single argument or input field to sanitize that subtree +- a field to trim all strings +""" +directive @trim on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\UnionDirective +""" +Use a custom function to determine the concrete type of unions. +""" +directive @union( + """ + Reference a function that returns the implementing Object Type. + Consists of two parts: a class name and a method name, seperated by an `@` symbol. + If you pass only a class name, the method name defaults to `__invoke`. + """ + resolveType: String! +) on UNION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\UpdateDirective +""" +Update an Eloquent model with the input values of the field. +""" +directive @update( + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String + + """ + Specify the name of the relation on the parent model. + This is only needed when using this directive as a nested arg + resolver and if the name of the relation is not the arg name. + """ + relation: String +) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\UploadDirective +""" +Uploads given file to storage, removes the argument and sets +the returned path to the attribute key provided. + +This does not change the schema from a client perspective. +""" +directive @upload( + """ + The storage disk to be used, defaults to config value `filesystems.default`. + """ + disk: String + + """ + The path where the file should be stored. + """ + path: String! = "/" + + """ + Should the visibility be public? + """ + public: Boolean! = false +) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\UpsertDirective +""" +Create or update an Eloquent model with the input values of the field. +""" +directive @upsert( + """ + Specify the class name of the model to use. + This is only needed when the default model detection does not work. + """ + model: String + + """ + DEPRECATED use @globalId, will be removed in v6 + + Set to `true` to use global ids for finding the model. + If set to `false`, regular non-global ids are used. + """ + globalId: Boolean = false + + """ + Specify the name of the relation on the parent model. + This is only needed when using this directive as a nested arg + resolver and if the name of the relation is not the arg name. + """ + relation: String +) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\WhereBetweenDirective +""" +Verify that a column's value is between two values. + +The type of the input value this is defined upon should be +an `input` object with two fields. +""" +directive @whereBetween( + """ + Specify the database column to compare. + Only required if database column has a different name than the attribute in your schema. + """ + key: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\WhereDirective +""" +Use an input value as a [where filter](https://laravel.com/docs/queries#where-clauses). +""" +directive @where( + """ + Specify the operator to use within the WHERE condition. + """ + operator: String = "=" + + """ + Specify the database column to compare. + Only required if database column has a different name than the attribute in your schema. + """ + key: String + + """ + Use Laravel's where clauses upon the query builder. + This only works for clauses with the signature (string $column, string $operator, mixed $value). + """ + clause: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\WhereJsonContainsDirective +""" +Use an input value as a [whereJsonContains filter](https://laravel.com/docs/queries#json-where-clauses). +""" +directive @whereJsonContains( + """ + Specify the database column and path inside the JSON to compare. + Only required if database column has a different name than the attribute in your schema. + """ + key: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\WhereNotBetweenDirective +""" +Verify that a column's value lies outside of two values. + +The type of the input value this is defined upon should be +an `input` object with two fields. +""" +directive @whereNotBetween( + """ + Specify the database column to compare. + Only required if database column has a different name than the attribute in your schema. + """ + key: String +) repeatable on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\WithCountDirective +""" +Eager-load the count of an Eloquent relation if the field is queried. + +Note that this does not return a value for the field, the count is simply +prefetched, assuming it is used to compute the field value. Use `@count` +if the field should simply return the relation count. +""" +directive @withCount( + """ + Specify the relationship method name in the model class. + """ + relation: String! + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) repeatable on FIELD_DEFINITION + +# Directive class: Nuwave\Lighthouse\Schema\Directives\WithDirective +""" +Eager-load an Eloquent relation. +""" +directive @with( + """ + Specify the relationship method name in the model class, + if it is named different from the field in the schema. + """ + relation: String + + """ + Apply scopes to the underlying query. + """ + scopes: [String!] +) repeatable on FIELD_DEFINITION