├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── composer.json ├── config ├── ConditionalOnModule │ ├── AccessControl │ │ └── Overrides │ │ │ └── services.yaml │ └── CacheControl │ │ ├── ConditionalOnModule │ │ └── AccessControl │ │ │ └── ConditionalOnContext │ │ │ └── PrivateSchema │ │ │ └── schema-services.yaml │ │ └── Overrides │ │ └── services.yaml ├── Overrides │ └── services.yaml ├── schema-services.yaml ├── services.yaml └── system-services.yaml ├── phpstan.neon ├── phpstan.neon.dist ├── src ├── AppStateProviderServices │ ├── GraphQLServerAppStateProviderService.php │ └── GraphQLServerAppStateProviderServiceInterface.php ├── Cache │ └── CacheTypes.php ├── ComponentProcessors │ ├── AbstractGraphQLRelationalFieldDataloadComponentProcessor.php │ ├── AbstractGraphQLRelationalFieldQueryDataComponentProcessor.php │ ├── GraphQLRelationalFieldQueryDataComponentProcessor.php │ ├── RootRelationalFieldDataloadComponentProcessor.php │ └── SuperRootGraphQLRelationalFieldDataloadComponentProcessor.php ├── ComponentRoutingProcessors │ └── EntryComponentRoutingProcessor.php ├── ConditionalOnModule │ ├── AccessControl │ │ └── Overrides │ │ │ └── Services │ │ │ └── AccessControlManager.php │ └── CacheControl │ │ ├── ConditionalOnModule │ │ └── AccessControl │ │ │ └── ConditionalOnContext │ │ │ └── PrivateSchema │ │ │ └── SchemaServices │ │ │ └── DirectiveResolvers │ │ │ └── SchemaNoCacheCacheControlFieldDirectiveResolver.php │ │ └── Overrides │ │ └── Services │ │ └── CacheControlManager.php ├── Configuration │ ├── MutationPayloadTypeOptions.php │ ├── MutationSchemes.php │ └── Request.php ├── Constants │ └── Params.php ├── Container │ ├── CompilerPasses │ │ ├── ConfigureGraphQLPersistedQueryCompilerPass.php │ │ └── RegisterMandatoryOperationDirectiveServiceTagCompilerPass.php │ └── ServiceTags │ │ └── MandatoryOperationDirectiveServiceTagInterface.php ├── Environment.php ├── Facades │ ├── AppStateProviderServices │ │ └── GraphQLServerAppStateProviderServiceFacade.php │ ├── Registries │ │ ├── MandatoryOperationDirectiveResolverRegistryFacade.php │ │ └── SchemaDefinitionReferenceRegistryFacade.php │ ├── Schema │ │ └── GraphQLSchemaDefinitionServiceFacade.php │ └── Syntax │ │ └── GraphQLSyntaxServiceFacade.php ├── FieldResolvers │ └── ObjectType │ │ ├── DirectiveExtensionsObjectTypeFieldResolver.php │ │ ├── DirectiveObjectTypeFieldResolver.php │ │ ├── EnumValueExtensionsObjectTypeFieldResolver.php │ │ ├── EnumValueObjectTypeFieldResolver.php │ │ ├── Extensions │ │ ├── DirectiveSchemaObjectTypeFieldResolver.php │ │ ├── FilterSystemDirectiveSchemaObjectTypeFieldResolver.php │ │ ├── SchemaObjectTypeFieldResolver.php │ │ └── TypeObjectTypeFieldResolver.php │ │ ├── FieldExtensionsObjectTypeFieldResolver.php │ │ ├── FieldObjectTypeFieldResolver.php │ │ ├── GlobalObjectTypeFieldResolver.php │ │ ├── InputValueExtensionsObjectTypeFieldResolver.php │ │ ├── InputValueObjectTypeFieldResolver.php │ │ ├── NamedTypeExtensionsObjectTypeFieldResolver.php │ │ ├── RegisterQueryAndMutationRootsRootObjectTypeFieldResolver.php │ │ ├── RootObjectTypeFieldResolver.php │ │ ├── SchemaExtensionsObjectTypeFieldResolver.php │ │ ├── SchemaObjectTypeFieldResolver.php │ │ ├── SuperRootObjectTypeFieldResolver.php │ │ └── TypeObjectTypeFieldResolver.php ├── Helpers │ ├── TypeResolverHelper.php │ └── TypeResolverHelperInterface.php ├── Hooks │ ├── DBEntriesHookSet.php │ ├── NestedMutationHookSet.php │ ├── RemoveIdentifiableObjectFieldsFromMutationRootObjectTypeHookSet.php │ ├── RemoveIdentifiableObjectFieldsFromSchemaElementExtensionsObjectTypeHookSet.php │ ├── SchemaCacheHookSet.php │ └── VarsHookSet.php ├── IFTTT │ ├── MandatoryDirectivesForFieldsRootTypeEntryDuplicator.php │ └── MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface.php ├── Module.php ├── ModuleConfiguration.php ├── ObjectFacades │ ├── MutationRootObjectFacade.php │ └── QueryRootObjectFacade.php ├── ObjectModels │ ├── AbstractNamedType.php │ ├── AbstractSchemaDefinitionReferenceObject.php │ ├── AbstractWrappingType.php │ ├── Directive.php │ ├── DirectiveExtensions.php │ ├── EnumType.php │ ├── EnumValue.php │ ├── EnumValueExtensions.php │ ├── Field.php │ ├── FieldExtensions.php │ ├── HasArgsSchemaDefinitionReferenceTrait.php │ ├── HasFieldsTypeInterface.php │ ├── HasFieldsTypeTrait.php │ ├── HasInterfacesTypeInterface.php │ ├── HasInterfacesTypeTrait.php │ ├── HasPossibleTypesTypeInterface.php │ ├── HasPossibleTypesTypeTrait.php │ ├── HasTypeSchemaDefinitionReferenceTrait.php │ ├── InputObjectType.php │ ├── InputValue.php │ ├── InputValueExtensions.php │ ├── InterfaceType.php │ ├── ListWrappingType.php │ ├── MutationRoot.php │ ├── NamedTypeExtensions.php │ ├── NamedTypeInterface.php │ ├── NonNullWrappingType.php │ ├── ObjectType.php │ ├── QueryRoot.php │ ├── ScalarType.php │ ├── Schema.php │ ├── SchemaDefinition │ │ └── RootObjectTypeSchemaDefinitionProvider.php │ ├── SchemaDefinitionReferenceObjectInterface.php │ ├── SchemaExtensions.php │ ├── TypeInterface.php │ ├── TypeKinds.php │ ├── UnionType.php │ └── WrappingTypeInterface.php ├── Overrides │ └── DataStructureFormatters │ │ └── GraphQLDataStructureFormatter.php ├── QueryResolution │ ├── GraphQLQueryASTTransformationService.php │ └── GraphQLQueryASTTransformationServiceInterface.php ├── Registries │ ├── MandatoryOperationDirectiveResolverRegistry.php │ ├── MandatoryOperationDirectiveResolverRegistryInterface.php │ ├── SchemaDefinitionReferenceRegistry.php │ └── SchemaDefinitionReferenceRegistryInterface.php ├── RelationalTypeDataLoaders │ └── ObjectType │ │ ├── MutationRootObjectTypeDataLoader.php │ │ ├── QueryRootObjectTypeDataLoader.php │ │ ├── SchemaDefinitionReferenceObjectTypeDataLoader.php │ │ ├── SchemaObjectTypeDataLoader.php │ │ └── WrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader.php ├── Schema │ ├── GraphQLSchemaDefinitionService.php │ ├── GraphQLSchemaDefinitionServiceInterface.php │ ├── GraphQLSchemaHelpers.php │ └── SchemaDefinitionHelpers.php ├── Server │ ├── AbstractAttachedGraphQLServer.php │ ├── AbstractGraphQLServer.php │ ├── AbstractSwitchAppThreadStandaloneGraphQLServer.php │ ├── GraphQLServerInterface.php │ └── StandaloneGraphQLServer.php ├── State │ └── AppStateProvider.php ├── Syntax │ ├── GraphQLSyntaxService.php │ └── GraphQLSyntaxServiceInterface.php └── TypeResolvers │ ├── EnumType │ ├── AbstractIntrospectionEnumTypeResolver.php │ ├── DirectiveKindEnumTypeResolver.php │ ├── DirectiveLocationEnumTypeResolver.php │ └── TypeKindEnumTypeResolver.php │ ├── IntrospectionTypeResolverTrait.php │ └── ObjectType │ ├── AbstractIntrospectionObjectTypeResolver.php │ ├── AbstractSchemaElementExtensionsObjectTypeResolver.php │ ├── AbstractUseRootAsSourceForSchemaObjectTypeResolver.php │ ├── DirectiveExtensionsObjectTypeResolver.php │ ├── DirectiveObjectTypeResolver.php │ ├── EnumValueExtensionsObjectTypeResolver.php │ ├── EnumValueObjectTypeResolver.php │ ├── FieldExtensionsObjectTypeResolver.php │ ├── FieldObjectTypeResolver.php │ ├── InputValueExtensionsObjectTypeResolver.php │ ├── InputValueObjectTypeResolver.php │ ├── MutationRootObjectTypeResolver.php │ ├── NamedTypeExtensionsObjectTypeResolver.php │ ├── QueryRootObjectTypeResolver.php │ ├── SchemaExtensionsObjectTypeResolver.php │ ├── SchemaObjectTypeResolver.php │ ├── TypeObjectTypeResolver.php │ └── UseRootAsSourceForSchemaObjectTypeResolverInterface.php └── tests ├── ModuleTest.php ├── QueryResolution ├── AbstractPrepareGraphQLForExecutionQueryASTTransformationServiceTestCase.php ├── MultipleQueryExecutionPrepareGraphQLForExecutionQueryASTTransformationServiceTest.php ├── NestedMutationsMultipleQueryExecutionPrepareGraphQLForExecutionQueryASTTransformationServiceTest.php ├── NestedMutationsPrepareGraphQLForExecutionQueryASTTransformationServiceTest.php └── PrepareGraphQLForExecutionQueryASTTransformationServiceTest.php └── Unit ├── AbstractConvertInputValueFromSingleToListFixtureQueryExecutionGraphQLServerTestCase.php ├── AbstractEnabledDisabledFixtureQueryExecutionGraphQLServerTestCase.php ├── AbstractExposeGlobalFieldsInGraphQLSchemaFixtureQueryExecutionGraphQLServerTestCase.php ├── AbstractFixtureQueryExecutionGraphQLServerTestCase.php ├── AbstractGraphQLServerTestCase.php ├── AbstractOrderedFieldsFixtureQueryExecutionGraphQLServerTestCase.php ├── AbstractQueryExecutionGraphQLServerTestCase.php ├── DisabledConvertInputValueFromSingleToListFixtureQueryExecutionGraphQLServerTest.php ├── DisabledExposeGlobalFieldsInGraphQLSchemaFixtureQueryExecutionGraphQLServerTest.php ├── DisabledFixtureQueryExecutionGraphQLServerTestCaseTrait.php ├── EnabledConvertInputValueFromSingleToListFixtureQueryExecutionGraphQLServerTest.php ├── EnabledDisabledFixtureQueryExecutionGraphQLServerTestCaseTrait.php ├── EnabledExposeGlobalFieldsInGraphQLSchemaFixtureQueryExecutionGraphQLServerTest.php ├── EnabledFixtureQueryExecutionGraphQLServerTestCaseTrait.php ├── FixtureQueryExecutionGraphQLServerTest.php ├── FixtureQueryExecutionGraphQLServerTestCaseTrait.php ├── FixtureTestCaseTrait.php ├── NamespacingFixtureQueryExecutionGraphQLServerTest.php ├── OrderedFieldsFixtureQueryExecutionGraphQLServerTest.php ├── QueryExecutionGraphQLServerTest.php ├── Upstream └── ComponentModel │ ├── InputValueCoercionQueryExecutionGraphQLServerTest.php │ └── VariablesQueryExecutionGraphQLServerTest.php ├── fixture-convert-input-value-from-single-to-list ├── array-input-passed-as-single-value.gql ├── array-input-passed-as-single-value@disabled.json └── array-input-passed-as-single-value@enabled.json ├── fixture-expose-global-fields-in-graphql-schema ├── introspection-global-fields.gql ├── introspection-global-fields@disabled.json ├── introspection-global-fields@enabled.json ├── introspection-query.gql ├── introspection-query@disabled.json ├── introspection-query@enabled.json ├── introspection-type-global-fields.gql ├── introspection-type-global-fields@disabled.json └── introspection-type-global-fields@enabled.json ├── fixture-namespacing ├── introspection-query.gql └── introspection-query.json ├── fixture-ordered-fields ├── error │ ├── response-entries-order.gql │ └── response-entries-order.json └── success │ ├── field-order.gql │ └── field-order.json └── fixture ├── error ├── directive-arg-type-mismatch.gql ├── directive-arg-type-mismatch.json ├── empty-query.gql ├── empty-query.json ├── explicit-null-fails-mandatory-directive-arg.gql ├── explicit-null-fails-mandatory-directive-arg.json ├── field-arg-type-mismatch.gql ├── field-arg-type-mismatch.json ├── field-is-not-connection.gql ├── field-is-not-connection.json ├── mandatory-directive-arg-not-provided.gql ├── mandatory-directive-arg-not-provided.json ├── mandatory-field-arg-not-provided.gql ├── mandatory-field-arg-not-provided.json ├── missing-variables.gql ├── missing-variables.json ├── non-existing-directive-arg-provided.gql ├── non-existing-directive-arg-provided.json ├── non-existing-directive.gql ├── non-existing-directive.json ├── non-existing-enum-value.gql ├── non-existing-enum-value.json ├── non-existing-field-arg-provided.gql ├── non-existing-field-arg-provided.json ├── non-existing-field.gql ├── non-existing-field.json ├── non-existing-fragment-spread-type.gql ├── non-existing-fragment-spread-type.json ├── non-existing-inline-fragment-spread-type.gql ├── non-existing-inline-fragment-spread-type.json ├── non-existing-multiple-fields.gql ├── non-existing-multiple-fields.json ├── non-existing-mutation.gql └── non-existing-mutation.json └── success ├── aliased-nested-self.gql ├── aliased-nested-self.json ├── directive-arg-allowed-type-mismatch.gql ├── directive-arg-allowed-type-mismatch.json ├── directive-in-fragment.gql ├── directive-in-fragment.json ├── directive-in-fragment.var.json ├── directive-in-inline-fragment.gql ├── directive-in-inline-fragment.json ├── directive-in-inline-fragment.var.json ├── enum.gql ├── enum.json ├── field-arg-allowed-type-mismatch.gql ├── field-arg-allowed-type-mismatch.json ├── id.gql ├── id.json ├── include-and-variables.gql ├── include-and-variables.json ├── include-and-variables.var.json ├── introspection-extensions.gql ├── introspection-extensions.json ├── introspection-query.gql ├── introspection-query.json ├── nested-fragments.gql ├── nested-fragments.json ├── nested-inline-fragments.gql ├── nested-inline-fragments.json ├── nested-self.gql ├── nested-self.json ├── self.gql ├── self.json ├── skip-connection.gql ├── skip-connection.json ├── skip-field.gql ├── skip-field.json ├── skip-not-connection.gql ├── skip-not-connection.json ├── skip-not-field.gql ├── skip-not-field.json ├── variable-inside-array.gql ├── variable-inside-array.json └── variable-inside-array.var.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: leoloso 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | composer.lock 3 | /vendor/ 4 | phpcs.xml 5 | phpunit.xml 6 | /.phpunit.cache 7 | -------------------------------------------------------------------------------- /config/ConditionalOnModule/AccessControl/Overrides/services.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | autowire: true 5 | autoconfigure: true 6 | 7 | PoP\AccessControl\Services\AccessControlManagerInterface: 8 | class: \GraphQLByPoP\GraphQLServer\ConditionalOnModule\AccessControl\Overrides\Services\AccessControlManager 9 | -------------------------------------------------------------------------------- /config/ConditionalOnModule/CacheControl/ConditionalOnModule/AccessControl/ConditionalOnContext/PrivateSchema/schema-services.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | autowire: true 5 | 6 | GraphQLByPoP\GraphQLServer\ConditionalOnModule\CacheControl\ConditionalOnModule\AccessControl\ConditionalOnContext\PrivateSchema\SchemaServices\: 7 | resource: '../../../../../../../src/ConditionalOnModule/CacheControl/ConditionalOnModule/AccessControl/ConditionalOnContext/PrivateSchema/SchemaServices/*' 8 | -------------------------------------------------------------------------------- /config/ConditionalOnModule/CacheControl/Overrides/services.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | autowire: true 5 | autoconfigure: true 6 | 7 | PoP\CacheControl\Managers\CacheControlManagerInterface: 8 | class: \GraphQLByPoP\GraphQLServer\ConditionalOnModule\CacheControl\Overrides\Services\CacheControlManager 9 | -------------------------------------------------------------------------------- /config/Overrides/services.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | autowire: true 5 | autoconfigure: true 6 | 7 | # Change the properties printed for the standard GraphQL response: 8 | PoPAPI\GraphQLAPI\DataStructureFormatters\GraphQLDataStructureFormatter: 9 | class: \GraphQLByPoP\GraphQLServer\Overrides\DataStructureFormatters\GraphQLDataStructureFormatter 10 | 11 | PoP\ComponentModel\Schema\SchemaDefinitionServiceInterface: 12 | class: \GraphQLByPoP\GraphQLServer\Schema\GraphQLSchemaDefinitionService 13 | 14 | PoP\Engine\Schema\SchemaDefinitionServiceInterface: 15 | class: \GraphQLByPoP\GraphQLServer\Schema\GraphQLSchemaDefinitionService 16 | 17 | PoPAPI\API\Schema\SchemaDefinitionServiceInterface: 18 | class: \GraphQLByPoP\GraphQLServer\Schema\GraphQLSchemaDefinitionService 19 | -------------------------------------------------------------------------------- /config/schema-services.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | autowire: true 5 | 6 | GraphQLByPoP\GraphQLServer\FieldResolvers\: 7 | resource: '../src/FieldResolvers/*' 8 | 9 | GraphQLByPoP\GraphQLServer\TypeResolvers\: 10 | resource: '../src/TypeResolvers/*' 11 | 12 | GraphQLByPoP\GraphQLServer\RelationalTypeDataLoaders\: 13 | resource: '../src/RelationalTypeDataLoaders/*' 14 | -------------------------------------------------------------------------------- /config/services.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | autowire: true 5 | autoconfigure: true 6 | 7 | GraphQLByPoP\GraphQLServer\Registries\MandatoryOperationDirectiveResolverRegistryInterface: 8 | class: \GraphQLByPoP\GraphQLServer\Registries\MandatoryOperationDirectiveResolverRegistry 9 | 10 | GraphQLByPoP\GraphQLServer\Registries\SchemaDefinitionReferenceRegistryInterface: 11 | class: \GraphQLByPoP\GraphQLServer\Registries\SchemaDefinitionReferenceRegistry 12 | 13 | GraphQLByPoP\GraphQLServer\Schema\GraphQLSchemaDefinitionServiceInterface: 14 | class: \GraphQLByPoP\GraphQLServer\Schema\GraphQLSchemaDefinitionService 15 | 16 | GraphQLByPoP\GraphQLServer\Syntax\GraphQLSyntaxServiceInterface: 17 | class: \GraphQLByPoP\GraphQLServer\Syntax\GraphQLSyntaxService 18 | 19 | GraphQLByPoP\GraphQLServer\QueryResolution\GraphQLQueryASTTransformationServiceInterface: 20 | class: \GraphQLByPoP\GraphQLServer\QueryResolution\GraphQLQueryASTTransformationService 21 | 22 | GraphQLByPoP\GraphQLServer\State\: 23 | resource: '../src/State/*' 24 | 25 | GraphQLByPoP\GraphQLServer\Hooks\: 26 | resource: '../src/Hooks/*' 27 | 28 | GraphQLByPoP\GraphQLServer\ComponentProcessors\: 29 | resource: '../src/ComponentProcessors/*' 30 | 31 | GraphQLByPoP\GraphQLServer\ComponentRoutingProcessors\: 32 | resource: '../src/ComponentRoutingProcessors/*' 33 | 34 | GraphQLByPoP\GraphQLServer\ObjectModels\QueryRoot: 35 | class: \GraphQLByPoP\GraphQLServer\ObjectModels\QueryRoot 36 | 37 | GraphQLByPoP\GraphQLServer\ObjectModels\MutationRoot: 38 | class: \GraphQLByPoP\GraphQLServer\ObjectModels\MutationRoot 39 | 40 | GraphQLByPoP\GraphQLServer\IFTTT\MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface: 41 | class: \GraphQLByPoP\GraphQLServer\IFTTT\MandatoryDirectivesForFieldsRootTypeEntryDuplicator 42 | 43 | GraphQLByPoP\GraphQLServer\Helpers\TypeResolverHelperInterface: 44 | class: \GraphQLByPoP\GraphQLServer\Helpers\TypeResolverHelper 45 | 46 | GraphQLByPoP\GraphQLServer\AppStateProviderServices\GraphQLServerAppStateProviderServiceInterface: 47 | class: \GraphQLByPoP\GraphQLServer\AppStateProviderServices\GraphQLServerAppStateProviderService 48 | -------------------------------------------------------------------------------- /config/system-services.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | autowire: true 5 | autoconfigure: true 6 | 7 | GraphQLByPoP\GraphQLServer\Container\CompilerPasses\: 8 | resource: '../src/Container/CompilerPasses/*' 9 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | includes: 2 | - phpstan.neon.dist 3 | -------------------------------------------------------------------------------- /phpstan.neon.dist: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 8 3 | paths: 4 | - src 5 | - tests 6 | -------------------------------------------------------------------------------- /src/AppStateProviderServices/GraphQLServerAppStateProviderService.php: -------------------------------------------------------------------------------- 1 | graphQLDataStructureFormatter === null) { 22 | /** @var GraphQLDataStructureFormatter */ 23 | $graphQLDataStructureFormatter = InstanceManagerFacade::getInstance()->getInstance(GraphQLDataStructureFormatter::class); 24 | $this->graphQLDataStructureFormatter = $graphQLDataStructureFormatter; 25 | } 26 | return $this->graphQLDataStructureFormatter; 27 | } 28 | 29 | /** 30 | * The required state to execute GraphQL queries. 31 | * 32 | * @return array 33 | */ 34 | public function getGraphQLRequestAppState(): array 35 | { 36 | return [ 37 | 'scheme' => Schemes::API, 38 | 'datastructure' => $this->getGraphQLDataStructureFormatter()->getName(), 39 | 'nature' => RequestNature::QUERY_ROOT, 40 | ]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/AppStateProviderServices/GraphQLServerAppStateProviderServiceInterface.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function getGraphQLRequestAppState(): array; 15 | } 16 | -------------------------------------------------------------------------------- /src/Cache/CacheTypes.php: -------------------------------------------------------------------------------- 1 | atts 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ComponentProcessors/AbstractGraphQLRelationalFieldQueryDataComponentProcessor.php: -------------------------------------------------------------------------------- 1 | graphQLQueryASTTransformationService === null) { 22 | /** @var GraphQLQueryASTTransformationServiceInterface */ 23 | $graphQLQueryASTTransformationService = $this->instanceManager->getInstance(GraphQLQueryASTTransformationServiceInterface::class); 24 | $this->graphQLQueryASTTransformationService = $graphQLQueryASTTransformationService; 25 | } 26 | return $this->graphQLQueryASTTransformationService; 27 | } 28 | 29 | /** 30 | * Convert the operations to include the SuperRoot Fields 31 | * 32 | * @return SplObjectStorage> 33 | */ 34 | protected function getOperationFieldOrFragmentBonds( 35 | ExecutableDocument $executableDocument, 36 | ): SplObjectStorage { 37 | $document = $executableDocument->getDocument(); 38 | /** @var OperationInterface[] */ 39 | $operations = $executableDocument->getMultipleOperationsToExecute(); 40 | return $this->getGraphQLQueryASTTransformationService()->prepareOperationFieldAndFragmentBondsForExecution( 41 | $document, 42 | $operations, 43 | $document->getFragments(), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/ComponentProcessors/GraphQLRelationalFieldQueryDataComponentProcessor.php: -------------------------------------------------------------------------------- 1 | superRootObjectTypeResolver === null) { 22 | /** @var SuperRootObjectTypeResolver */ 23 | $superRootObjectTypeResolver = $this->instanceManager->getInstance(SuperRootObjectTypeResolver::class); 24 | $this->superRootObjectTypeResolver = $superRootObjectTypeResolver; 25 | } 26 | return $this->superRootObjectTypeResolver; 27 | } 28 | 29 | /** 30 | * @return string[] 31 | */ 32 | public function getComponentNamesToProcess(): array 33 | { 34 | return array( 35 | self::COMPONENT_DATALOAD_RELATIONALFIELDS_SUPERROOT, 36 | ); 37 | } 38 | 39 | /** 40 | * @return string|int|array|null 41 | * @param array $props 42 | * @param array $data_properties 43 | */ 44 | public function getObjectIDOrIDs(Component $component, array &$props, array &$data_properties): string|int|array|null 45 | { 46 | if (App::getState('does-api-query-have-errors')) { 47 | return null; 48 | } 49 | switch ($component->name) { 50 | case self::COMPONENT_DATALOAD_RELATIONALFIELDS_SUPERROOT: 51 | return SuperRoot::ID; 52 | } 53 | return parent::getObjectIDOrIDs($component, $props, $data_properties); 54 | } 55 | 56 | public function getRelationalTypeResolver(Component $component): ?RelationalTypeResolverInterface 57 | { 58 | switch ($component->name) { 59 | case self::COMPONENT_DATALOAD_RELATIONALFIELDS_SUPERROOT: 60 | return $this->getSuperRootObjectTypeResolver(); 61 | } 62 | 63 | return parent::getRelationalTypeResolver($component); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/ComponentRoutingProcessors/EntryComponentRoutingProcessor.php: -------------------------------------------------------------------------------- 1 | graphQLDataStructureFormatter === null) { 21 | /** @var GraphQLDataStructureFormatter */ 22 | $graphQLDataStructureFormatter = $this->instanceManager->getInstance(GraphQLDataStructureFormatter::class); 23 | $this->graphQLDataStructureFormatter = $graphQLDataStructureFormatter; 24 | } 25 | return $this->graphQLDataStructureFormatter; 26 | } 27 | 28 | /** 29 | * @return array>> 30 | */ 31 | public function getStatePropertiesToSelectComponentByNature(): array 32 | { 33 | $ret = array(); 34 | 35 | $ret[RequestNature::QUERY_ROOT][] = [ 36 | 'component' => new Component( 37 | SuperRootGraphQLRelationalFieldDataloadComponentProcessor::class, 38 | SuperRootGraphQLRelationalFieldDataloadComponentProcessor::COMPONENT_DATALOAD_RELATIONALFIELDS_SUPERROOT 39 | ), 40 | 'conditions' => [ 41 | 'scheme' => APISchemes::API, 42 | 'datastructure' => $this->getGraphQLDataStructureFormatter()->getName(), 43 | ], 44 | ]; 45 | 46 | return $ret; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/ConditionalOnModule/AccessControl/Overrides/Services/AccessControlManager.php: -------------------------------------------------------------------------------- 1 | > 14 | */ 15 | protected array $overriddenFieldEntries = []; 16 | 17 | private ?MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface $mandatoryDirectivesForFieldsRootTypeEntryDuplicator = null; 18 | 19 | final protected function getMandatoryDirectivesForFieldsRootTypeEntryDuplicator(): MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface 20 | { 21 | if ($this->mandatoryDirectivesForFieldsRootTypeEntryDuplicator === null) { 22 | /** @var MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface */ 23 | $mandatoryDirectivesForFieldsRootTypeEntryDuplicator = $this->instanceManager->getInstance(MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface::class); 24 | $this->mandatoryDirectivesForFieldsRootTypeEntryDuplicator = $mandatoryDirectivesForFieldsRootTypeEntryDuplicator; 25 | } 26 | return $this->mandatoryDirectivesForFieldsRootTypeEntryDuplicator; 27 | } 28 | 29 | /** 30 | * @param array $fieldEntries 31 | */ 32 | public function addEntriesForFields(string $group, array $fieldEntries): void 33 | { 34 | parent::addEntriesForFields($group, $fieldEntries); 35 | 36 | // Make sure to reset getting the entries 37 | unset($this->overriddenFieldEntries[$group]); 38 | } 39 | 40 | /** 41 | * Add additional entries: whenever Root is used, 42 | * duplicate it also for both QueryRoot and MutationRoot, 43 | * so that the user needs to set the configuration only once. 44 | * 45 | * Add this logic when retrieving the entries because by then 46 | * the container is compiled and we can access the RootObjectTypeResolver 47 | * instance. In contrast, `addEntriesForFields` can be called 48 | * within a CompilerPass, so the instances would not yet be available. 49 | * 50 | * @return array 51 | */ 52 | public function getEntriesForFields(string $group): array 53 | { 54 | if (isset($this->overriddenFieldEntries[$group])) { 55 | return $this->overriddenFieldEntries[$group]; 56 | } 57 | 58 | $this->overriddenFieldEntries[$group] = $this->getMandatoryDirectivesForFieldsRootTypeEntryDuplicator()->maybeAppendAdditionalRootEntriesForFields( 59 | parent::getEntriesForFields($group) 60 | ); 61 | 62 | return $this->overriddenFieldEntries[$group]; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/ConditionalOnModule/CacheControl/ConditionalOnModule/AccessControl/ConditionalOnContext/PrivateSchema/SchemaServices/DirectiveResolvers/SchemaNoCacheCacheControlFieldDirectiveResolver.php: -------------------------------------------------------------------------------- 1 | |null 14 | */ 15 | protected ?array $overriddenFieldEntries = null; 16 | 17 | private ?MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface $mandatoryDirectivesForFieldsRootTypeEntryDuplicator = null; 18 | 19 | final protected function getMandatoryDirectivesForFieldsRootTypeEntryDuplicator(): MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface 20 | { 21 | if ($this->mandatoryDirectivesForFieldsRootTypeEntryDuplicator === null) { 22 | /** @var MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface */ 23 | $mandatoryDirectivesForFieldsRootTypeEntryDuplicator = $this->instanceManager->getInstance(MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface::class); 24 | $this->mandatoryDirectivesForFieldsRootTypeEntryDuplicator = $mandatoryDirectivesForFieldsRootTypeEntryDuplicator; 25 | } 26 | return $this->mandatoryDirectivesForFieldsRootTypeEntryDuplicator; 27 | } 28 | 29 | /** 30 | * @param array $fieldEntries 31 | */ 32 | public function addEntriesForFields(array $fieldEntries): void 33 | { 34 | parent::addEntriesForFields($fieldEntries); 35 | 36 | // Make sure to reset getting the entries 37 | $this->overriddenFieldEntries = null; 38 | } 39 | 40 | /** 41 | * Add additional entries: whenever Root is used, 42 | * duplicate it also for both QueryRoot and MutationRoot, 43 | * so that the user needs to set the configuration only once. 44 | * 45 | * Add this logic when retrieving the entries because by then 46 | * the container is compiled and we can access the RootObjectTypeResolver 47 | * instance. In contrast, `addEntriesForFields` can be called 48 | * within a CompilerPass, so the instances would not yet be available. 49 | * 50 | * @return array 51 | */ 52 | public function getEntriesForFields(): array 53 | { 54 | if ($this->overriddenFieldEntries !== null) { 55 | return $this->overriddenFieldEntries; 56 | } 57 | 58 | $this->overriddenFieldEntries = $this->getMandatoryDirectivesForFieldsRootTypeEntryDuplicator()->maybeAppendAdditionalRootEntriesForFields( 59 | parent::getEntriesForFields() 60 | ); 61 | 62 | return $this->overriddenFieldEntries; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Configuration/MutationPayloadTypeOptions.php: -------------------------------------------------------------------------------- 1 | get(GraphQLServerAppStateProviderServiceInterface::class); 18 | return $service; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Facades/Registries/MandatoryOperationDirectiveResolverRegistryFacade.php: -------------------------------------------------------------------------------- 1 | get(MandatoryOperationDirectiveResolverRegistryInterface::class); 18 | return $service; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Facades/Registries/SchemaDefinitionReferenceRegistryFacade.php: -------------------------------------------------------------------------------- 1 | get(SchemaDefinitionReferenceRegistryInterface::class); 18 | return $service; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Facades/Schema/GraphQLSchemaDefinitionServiceFacade.php: -------------------------------------------------------------------------------- 1 | get(GraphQLSchemaDefinitionServiceInterface::class); 18 | return $service; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Facades/Syntax/GraphQLSyntaxServiceFacade.php: -------------------------------------------------------------------------------- 1 | get(GraphQLSyntaxServiceInterface::class); 18 | return $service; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Helpers/TypeResolverHelper.php: -------------------------------------------------------------------------------- 1 | moveEntriesUnderDBName(...) 18 | ); 19 | } 20 | 21 | /** 22 | * All fields starting with "__" (such as "__schema") are meta 23 | * 24 | * @param string[] $metaFields 25 | * @return string[] 26 | */ 27 | public function moveEntriesUnderDBName(array $metaFields): array 28 | { 29 | $metaFields[] = '__schema'; 30 | $metaFields[] = '__typename'; 31 | $metaFields[] = '__type'; 32 | return $metaFields; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Hooks/RemoveIdentifiableObjectFieldsFromMutationRootObjectTypeHookSet.php: -------------------------------------------------------------------------------- 1 | 24 | */ 25 | protected function getObjectTypeOrInterfaceTypeResolverClass(): string 26 | { 27 | return MutationRootObjectTypeResolver::class; 28 | } 29 | 30 | public function isServiceEnabled(): bool 31 | { 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Hooks/RemoveIdentifiableObjectFieldsFromSchemaElementExtensionsObjectTypeHookSet.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | protected function getObjectTypeOrInterfaceTypeResolverClass(): string 18 | { 19 | return AbstractSchemaElementExtensionsObjectTypeResolver::class; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Hooks/SchemaCacheHookSet.php: -------------------------------------------------------------------------------- 1 | getSchemaCacheKeyElements(...) 22 | ); 23 | } 24 | 25 | /** 26 | * @return array 27 | * @param string[] $elements 28 | */ 29 | public function getSchemaCacheKeyElements(array $elements): array 30 | { 31 | /** @var ComponentModelModuleConfiguration */ 32 | $componentModelModuleConfiguration = App::getModule(ComponentModelModule::class)->getConfiguration(); 33 | if (!$componentModelModuleConfiguration->supportDefiningServicesInTheContainerBasedOnTheContext()) { 34 | return $elements; 35 | } 36 | 37 | /** @var ModuleConfiguration */ 38 | $moduleConfiguration = App::getModule(Module::class)->getConfiguration(); 39 | $elements['nested-mutations-enabled'] = $moduleConfiguration->enableNestedMutations(); 40 | return $elements; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Hooks/VarsHookSet.php: -------------------------------------------------------------------------------- 1 | getModelInstanceElementsFromAppState(...) 22 | ); 23 | } 24 | 25 | /** 26 | * @return string[] 27 | * @param string[] $elements 28 | */ 29 | public function getModelInstanceElementsFromAppState(array $elements): array 30 | { 31 | /** @var ComponentModelModuleConfiguration */ 32 | $moduleConfiguration = App::getModule(ComponentModelModule::class)->getConfiguration(); 33 | $elements[] = $this->__('edit schema:', 'graphql-server') . $moduleConfiguration->includeSchemaTypeDirectivesInSchema(); 34 | 35 | /** @var ModuleConfiguration */ 36 | $moduleConfiguration = App::getModule(Module::class)->getConfiguration(); 37 | $elements[] = $this->__('enable nested mutations:', 'graphql-server') . $moduleConfiguration->enableNestedMutations(); 38 | $elements[] = $this->__('enable GraphQL introspection:', 'graphql-server') . App::getState('graphql-introspection-enabled'); 39 | 40 | return $elements; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/IFTTT/MandatoryDirectivesForFieldsRootTypeEntryDuplicatorInterface.php: -------------------------------------------------------------------------------- 1 | The same array $fieldEntries + appended entries for QueryRoot and MutationRoot 27 | * @param array $fieldEntries 28 | */ 29 | public function maybeAppendAdditionalRootEntriesForFields(array $fieldEntries, bool $forceBothTypes = false): array; 30 | } 31 | -------------------------------------------------------------------------------- /src/ObjectFacades/MutationRootObjectFacade.php: -------------------------------------------------------------------------------- 1 | get(MutationRoot::class); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ObjectFacades/QueryRootObjectFacade.php: -------------------------------------------------------------------------------- 1 | get(QueryRoot::class); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ObjectModels/AbstractNamedType.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 15 | * @param string[] $schemaDefinitionPath 16 | */ 17 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 18 | { 19 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 20 | 21 | /** @var string[] */ 22 | $namedTypeExtensionsSchemaDefinitionPath = array_merge( 23 | $schemaDefinitionPath, 24 | [ 25 | SchemaDefinition::EXTENSIONS, 26 | ] 27 | ); 28 | $this->namedTypeExtensions = new NamedTypeExtensions($fullSchemaDefinition, $namedTypeExtensionsSchemaDefinitionPath); 29 | } 30 | 31 | public function getNamespacedName(): string 32 | { 33 | return $this->schemaDefinition[SchemaDefinition::EXTENSIONS][SchemaDefinition::NAMESPACED_NAME]; 34 | } 35 | 36 | public function getElementName(): string 37 | { 38 | return $this->schemaDefinition[SchemaDefinition::EXTENSIONS][SchemaDefinition::ELEMENT_NAME]; 39 | } 40 | 41 | public function getName(): string 42 | { 43 | return $this->schemaDefinition[SchemaDefinition::NAME]; 44 | } 45 | 46 | public function getDescription(): ?string 47 | { 48 | return $this->schemaDefinition[SchemaDefinition::DESCRIPTION] ?? null; 49 | } 50 | 51 | public function getExtensions(): NamedTypeExtensions 52 | { 53 | return $this->namedTypeExtensions; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ObjectModels/AbstractSchemaDefinitionReferenceObject.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | protected array $schemaDefinition; 16 | 17 | /** 18 | * Build a new Schema Definition Reference Object 19 | * @param array $fullSchemaDefinition 20 | * @param string[] $schemaDefinitionPath 21 | */ 22 | public function __construct(/** @var array */ 23 | protected array &$fullSchemaDefinition, 24 | /** @var string[] */ 25 | protected array $schemaDefinitionPath, 26 | ) { 27 | // Retrieve this element's schema definition by iterating down its path starting from the root of the full schema definition 28 | $schemaDefinitionPointer = &$fullSchemaDefinition; 29 | foreach ($schemaDefinitionPath as $pathLevel) { 30 | $schemaDefinitionPointer = &$schemaDefinitionPointer[$pathLevel]; 31 | } 32 | $this->schemaDefinition = $schemaDefinitionPointer; 33 | 34 | // Register the object, and get back its ID 35 | $schemaDefinitionReferenceRegistry = SchemaDefinitionReferenceRegistryFacade::getInstance(); 36 | $this->id = $schemaDefinitionReferenceRegistry->registerSchemaDefinitionReferenceObject($this); 37 | } 38 | 39 | /** 40 | * @return array 41 | */ 42 | public function getSchemaDefinition(): array 43 | { 44 | return $this->schemaDefinition; 45 | } 46 | 47 | /** 48 | * @return string[] 49 | */ 50 | public function getSchemaDefinitionPath(): array 51 | { 52 | return $this->schemaDefinitionPath; 53 | } 54 | 55 | public function getID(): string 56 | { 57 | return $this->id; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/ObjectModels/AbstractWrappingType.php: -------------------------------------------------------------------------------- 1 | wrappedType; 17 | } 18 | 19 | public function getWrappedTypeID(): string 20 | { 21 | return $this->wrappedType->getID(); 22 | } 23 | 24 | public function getDescription(): ?string 25 | { 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ObjectModels/Directive.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 17 | * @param string[] $schemaDefinitionPath 18 | */ 19 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 20 | { 21 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 22 | 23 | /** @var string[] */ 24 | $directiveExtensionsSchemaDefinitionPath = array_merge( 25 | $schemaDefinitionPath, 26 | [ 27 | SchemaDefinition::EXTENSIONS, 28 | ] 29 | ); 30 | $this->directiveExtensions = new DirectiveExtensions($fullSchemaDefinition, $directiveExtensionsSchemaDefinitionPath); 31 | 32 | $this->initArgs($fullSchemaDefinition, $schemaDefinitionPath); 33 | } 34 | 35 | public function getName(): string 36 | { 37 | return $this->schemaDefinition[SchemaDefinition::NAME]; 38 | } 39 | 40 | public function getDescription(): ?string 41 | { 42 | return $this->schemaDefinition[SchemaDefinition::DESCRIPTION] ?? null; 43 | } 44 | 45 | /** 46 | * @return string[] 47 | */ 48 | public function getLocations(): array 49 | { 50 | return $this->schemaDefinition[SchemaDefinition::DIRECTIVE_LOCATIONS]; 51 | } 52 | 53 | public function isRepeatable(): bool 54 | { 55 | return $this->schemaDefinition[SchemaDefinition::DIRECTIVE_IS_REPEATABLE]; 56 | } 57 | 58 | public function getKind(): string 59 | { 60 | return $this->schemaDefinition[SchemaDefinition::DIRECTIVE_KIND]; 61 | } 62 | 63 | public function getExtensions(): DirectiveExtensions 64 | { 65 | return $this->directiveExtensions; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ObjectModels/DirectiveExtensions.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::DIRECTIVE_NEEDS_DATA_TO_EXECUTE]; 14 | } 15 | 16 | /** 17 | * @return string[]|null 18 | */ 19 | public function getFieldDirectiveSupportedTypeNamesOrDescriptions(): ?array 20 | { 21 | return $this->schemaDefinition[SchemaDefinition::FIELD_DIRECTIVE_SUPPORTED_TYPE_NAMES_OR_DESCRIPTIONS]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ObjectModels/EnumType.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 18 | * @param string[] $schemaDefinitionPath 19 | */ 20 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 21 | { 22 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 23 | 24 | $this->initEnumValues($fullSchemaDefinition, $schemaDefinitionPath); 25 | } 26 | /** 27 | * @param array $fullSchemaDefinition 28 | * @param string[] $schemaDefinitionPath 29 | */ 30 | protected function initEnumValues(array &$fullSchemaDefinition, array $schemaDefinitionPath): void 31 | { 32 | $this->enumValues = []; 33 | $enumItems = $this->schemaDefinition[SchemaDefinition::ITEMS]; 34 | /** @var string $enumValue */ 35 | foreach (array_keys($enumItems) as $enumValue) { 36 | /** @var string[] */ 37 | $enumValueSchemaDefinitionPath = array_merge( 38 | $schemaDefinitionPath, 39 | [ 40 | SchemaDefinition::ITEMS, 41 | $enumValue, 42 | ] 43 | ); 44 | $this->enumValues[] = new EnumValue( 45 | $fullSchemaDefinition, 46 | $enumValueSchemaDefinitionPath 47 | ); 48 | } 49 | } 50 | 51 | public function getKind(): string 52 | { 53 | return TypeKinds::ENUM; 54 | } 55 | /** 56 | * @return EnumValue[] 57 | */ 58 | public function getEnumValues(bool $includeDeprecated = false): array 59 | { 60 | return $includeDeprecated ? 61 | $this->enumValues : 62 | array_filter( 63 | $this->enumValues, 64 | function (EnumValue $enumValue): bool { 65 | return !$enumValue->isDeprecated(); 66 | } 67 | ); 68 | } 69 | /** 70 | * @return string[] 71 | */ 72 | public function getEnumValueIDs(bool $includeDeprecated = false): array 73 | { 74 | return array_map( 75 | function (EnumValue $enumValue): string { 76 | return $enumValue->getID(); 77 | }, 78 | $this->getEnumValues($includeDeprecated) 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/ObjectModels/EnumValue.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 15 | * @param string[] $schemaDefinitionPath 16 | */ 17 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 18 | { 19 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 20 | 21 | /** @var string[] */ 22 | $enumValueExtensionsSchemaDefinitionPath = array_merge( 23 | $schemaDefinitionPath, 24 | [ 25 | SchemaDefinition::EXTENSIONS, 26 | ] 27 | ); 28 | $this->enumValueExtensions = new EnumValueExtensions($fullSchemaDefinition, $enumValueExtensionsSchemaDefinitionPath); 29 | } 30 | 31 | public function getName(): string 32 | { 33 | return $this->getValue(); 34 | } 35 | public function getValue(): string 36 | { 37 | return $this->schemaDefinition[SchemaDefinition::VALUE]; 38 | } 39 | public function getDescription(): ?string 40 | { 41 | return $this->schemaDefinition[SchemaDefinition::DESCRIPTION] ?? null; 42 | } 43 | public function isDeprecated(): bool 44 | { 45 | return $this->schemaDefinition[SchemaDefinition::DEPRECATED] ?? false; 46 | } 47 | public function getDeprecatedReason(): ?string 48 | { 49 | return $this->schemaDefinition[SchemaDefinition::DEPRECATION_MESSAGE] ?? null; 50 | } 51 | public function getExtensions(): EnumValueExtensions 52 | { 53 | return $this->enumValueExtensions; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ObjectModels/EnumValueExtensions.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::IS_SENSITIVE_DATA_ELEMENT]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ObjectModels/Field.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 18 | * @param string[] $schemaDefinitionPath 19 | */ 20 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 21 | { 22 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 23 | 24 | /** @var string[] */ 25 | $fieldExtensionsSchemaDefinitionPath = array_merge( 26 | $schemaDefinitionPath, 27 | [ 28 | SchemaDefinition::EXTENSIONS, 29 | ] 30 | ); 31 | $this->fieldExtensions = new FieldExtensions($fullSchemaDefinition, $fieldExtensionsSchemaDefinitionPath); 32 | 33 | $this->initArgs($fullSchemaDefinition, $schemaDefinitionPath); 34 | } 35 | public function getName(): string 36 | { 37 | return $this->schemaDefinition[SchemaDefinition::NAME]; 38 | } 39 | public function getDescription(): ?string 40 | { 41 | return $this->schemaDefinition[SchemaDefinition::DESCRIPTION] ?? null; 42 | } 43 | public function isDeprecated(): bool 44 | { 45 | return $this->schemaDefinition[SchemaDefinition::DEPRECATED] ?? false; 46 | } 47 | public function getDeprecationMessage(): ?string 48 | { 49 | return $this->schemaDefinition[SchemaDefinition::DEPRECATION_MESSAGE] ?? null; 50 | } 51 | public function getExtensions(): FieldExtensions 52 | { 53 | return $this->fieldExtensions; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ObjectModels/FieldExtensions.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::FIELD_IS_GLOBAL]; 14 | } 15 | 16 | public function isMutation(): bool 17 | { 18 | return $this->schemaDefinition[SchemaDefinition::FIELD_IS_MUTATION]; 19 | } 20 | 21 | public function isSensitiveDataElement(): bool 22 | { 23 | return $this->schemaDefinition[SchemaDefinition::IS_SENSITIVE_DATA_ELEMENT]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ObjectModels/HasArgsSchemaDefinitionReferenceTrait.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 18 | * @param string[] $schemaDefinitionPath 19 | */ 20 | protected function initArgs(array &$fullSchemaDefinition, array $schemaDefinitionPath): void 21 | { 22 | $this->args = []; 23 | if ($args = $this->schemaDefinition[SchemaDefinition::ARGS] ?? null) { 24 | /** @var string $fieldArgName */ 25 | foreach (array_keys($args) as $fieldArgName) { 26 | /** @var string[] */ 27 | $fieldArgSchemaDefinitionPath = array_merge( 28 | $schemaDefinitionPath, 29 | [ 30 | SchemaDefinition::ARGS, 31 | $fieldArgName, 32 | ] 33 | ); 34 | $this->args[] = new InputValue( 35 | $fullSchemaDefinition, 36 | $fieldArgSchemaDefinitionPath 37 | ); 38 | } 39 | } 40 | } 41 | /** 42 | * Implementation of "args" field from the Field object 43 | * 44 | * @return InputValue[] 45 | * 46 | * @see https://graphql.github.io/graphql-spec/draft/#sel-FAJbLACsEIDuEAA-vb 47 | */ 48 | public function getArgs(): array 49 | { 50 | return $this->args; 51 | } 52 | /** 53 | * @return string[] 54 | */ 55 | public function getArgIDs(): array 56 | { 57 | return array_map( 58 | function (InputValue $inputValue): string { 59 | return $inputValue->getID(); 60 | }, 61 | $this->getArgs() 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/ObjectModels/HasFieldsTypeInterface.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::INTERFACES] ?? []) as $interfaceTypeName) { 21 | $interfaceIDs[] = SchemaDefinitionHelpers::getSchemaDefinitionReferenceObjectID([ 22 | SchemaDefinition::TYPES, 23 | TypeKinds::INTERFACE, 24 | $interfaceTypeName, 25 | ]); 26 | } 27 | return $interfaceIDs; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ObjectModels/HasPossibleTypesTypeInterface.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::POSSIBLE_TYPES]) as $objectTypeName) { 21 | $possibleTypeIDs[] = SchemaDefinitionHelpers::getSchemaDefinitionReferenceObjectID([ 22 | SchemaDefinition::TYPES, 23 | TypeKinds::OBJECT, 24 | $objectTypeName, 25 | ]); 26 | } 27 | return $possibleTypeIDs; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ObjectModels/HasTypeSchemaDefinitionReferenceTrait.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::TYPE_KIND], 22 | $this->schemaDefinition[SchemaDefinition::TYPE_NAME], 23 | ]); 24 | return GraphQLSchemaHelpers::getMaybeWrappedTypeName( 25 | $typeID, 26 | $this->schemaDefinition[SchemaDefinition::NON_NULLABLE] ?? $this->schemaDefinition[SchemaDefinition::MANDATORY] ?? null, 27 | $this->schemaDefinition[SchemaDefinition::IS_ARRAY] ?? false, 28 | $this->schemaDefinition[SchemaDefinition::IS_NON_NULLABLE_ITEMS_IN_ARRAY] ?? false, 29 | $this->schemaDefinition[SchemaDefinition::IS_ARRAY_OF_ARRAYS] ?? false, 30 | $this->schemaDefinition[SchemaDefinition::IS_NON_NULLABLE_ITEMS_IN_ARRAY_OF_ARRAYS] ?? false, 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/ObjectModels/InputObjectType.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 18 | * @param string[] $schemaDefinitionPath 19 | */ 20 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 21 | { 22 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 23 | 24 | $this->initInputValues($fullSchemaDefinition, $schemaDefinitionPath); 25 | } 26 | /** 27 | * @param array $fullSchemaDefinition 28 | * @param string[] $schemaDefinitionPath 29 | */ 30 | protected function initInputValues(array &$fullSchemaDefinition, array $schemaDefinitionPath): void 31 | { 32 | $this->inputValues = []; 33 | if ($inputValues = $this->schemaDefinition[SchemaDefinition::INPUT_FIELDS] ?? null) { 34 | /** @var string $inputValueName */ 35 | foreach (array_keys($inputValues) as $inputValueName) { 36 | /** @var string[] */ 37 | $inputValueSchemaDefinitionPath = array_merge( 38 | $schemaDefinitionPath, 39 | [ 40 | SchemaDefinition::INPUT_FIELDS, 41 | $inputValueName, 42 | ] 43 | ); 44 | $this->inputValues[] = new InputValue( 45 | $fullSchemaDefinition, 46 | $inputValueSchemaDefinitionPath 47 | ); 48 | } 49 | } 50 | } 51 | 52 | public function getKind(): string 53 | { 54 | return TypeKinds::INPUT_OBJECT; 55 | } 56 | /** 57 | * @return InputValue[] 58 | */ 59 | public function getInputFields(): array 60 | { 61 | return $this->inputValues; 62 | } 63 | /** 64 | * @return string[] 65 | */ 66 | public function getInputFieldIDs(): array 67 | { 68 | return array_map( 69 | function (InputValue $inputValue): string { 70 | return $inputValue->getID(); 71 | }, 72 | $this->getInputFields() 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/ObjectModels/InputValue.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 17 | * @param string[] $schemaDefinitionPath 18 | */ 19 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 20 | { 21 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 22 | 23 | /** @var string[] */ 24 | $inputValueExtensionsSchemaDefinitionPath = array_merge( 25 | $schemaDefinitionPath, 26 | [ 27 | SchemaDefinition::EXTENSIONS, 28 | ] 29 | ); 30 | $this->inputValueExtensions = new InputValueExtensions($fullSchemaDefinition, $inputValueExtensionsSchemaDefinitionPath); 31 | } 32 | 33 | public function getName(): string 34 | { 35 | return $this->schemaDefinition[SchemaDefinition::NAME]; 36 | } 37 | public function getDescription(): ?string 38 | { 39 | return $this->schemaDefinition[SchemaDefinition::DESCRIPTION] ?? null; 40 | } 41 | 42 | /** 43 | * The default value must be returned as a JSON encoded string. 44 | * 45 | * From the GraphQL spec: 46 | * 47 | * defaultValue may return a String encoding (using the GraphQL language) 48 | * of the default value used by this input value in the condition a value 49 | * is not provided at runtime. If this input value has no default value, 50 | * returns null. 51 | * 52 | * @see http://spec.graphql.org/draft/#sec-The-__InputValue-Type 53 | */ 54 | public function getDefaultValue(): ?string 55 | { 56 | $defaultValue = $this->schemaDefinition[SchemaDefinition::DEFAULT_VALUE] ?? null; 57 | if ($defaultValue === null) { 58 | return null; 59 | } 60 | return (string)json_encode($defaultValue); 61 | } 62 | 63 | public function getExtensions(): InputValueExtensions 64 | { 65 | return $this->inputValueExtensions; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ObjectModels/InputValueExtensions.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::IS_SENSITIVE_DATA_ELEMENT]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ObjectModels/InterfaceType.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 15 | * @param string[] $schemaDefinitionPath 16 | */ 17 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 18 | { 19 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 20 | 21 | $this->initFields($fullSchemaDefinition, $schemaDefinitionPath); 22 | } 23 | 24 | public function getKind(): string 25 | { 26 | return TypeKinds::INTERFACE; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ObjectModels/ListWrappingType.php: -------------------------------------------------------------------------------- 1 | wrappedType->getName()); 14 | } 15 | 16 | public function getID(): string 17 | { 18 | return GraphQLSchemaHelpers::getListTypeName($this->wrappedType->getID()); 19 | } 20 | 21 | public function getKind(): string 22 | { 23 | return TypeKinds::LIST; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ObjectModels/MutationRoot.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::ELEMENT_NAME]; 14 | } 15 | 16 | public function getTypeNamespacedName(): string 17 | { 18 | return $this->schemaDefinition[SchemaDefinition::NAMESPACED_NAME]; 19 | } 20 | 21 | /** 22 | * Enum-like "possible values" for EnumString type resolvers, `null` otherwise 23 | * 24 | * @return string[]|null 25 | */ 26 | public function getTypePossibleValues(): ?array 27 | { 28 | return $this->schemaDefinition[SchemaDefinition::POSSIBLE_VALUES] ?? null; 29 | } 30 | 31 | /** 32 | * @see https://github.com/graphql/graphql-spec/pull/825 33 | * 34 | * > OneOf Input Objects are a special variant of Input Objects 35 | * > where the type system asserts that exactly one of the fields 36 | * > must be set and non-null, all others being omitted. 37 | * > This is represented in introspection with the 38 | * __Type.isOneOf: Boolean field. 39 | */ 40 | public function getTypeIsOneOfInputObjectType(): bool 41 | { 42 | return $this->schemaDefinition[SchemaDefinition::IS_ONE_OF] ?? false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/ObjectModels/NamedTypeInterface.php: -------------------------------------------------------------------------------- 1 | wrappedType->getName()); 14 | } 15 | 16 | public function getID(): string 17 | { 18 | return GraphQLSchemaHelpers::getNonNullTypeName($this->wrappedType->getID()); 19 | } 20 | 21 | public function getKind(): string 22 | { 23 | return TypeKinds::NON_NULL; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ObjectModels/ObjectType.php: -------------------------------------------------------------------------------- 1 | $fullSchemaDefinition 14 | * @param string[] $schemaDefinitionPath 15 | */ 16 | public function __construct(array &$fullSchemaDefinition, array $schemaDefinitionPath) 17 | { 18 | parent::__construct($fullSchemaDefinition, $schemaDefinitionPath); 19 | 20 | $this->initFields($fullSchemaDefinition, $schemaDefinitionPath); 21 | } 22 | 23 | public function getKind(): string 24 | { 25 | return TypeKinds::OBJECT; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ObjectModels/QueryRoot.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::SPECIFIED_BY_URL] ?? null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ObjectModels/SchemaDefinition/RootObjectTypeSchemaDefinitionProvider.php: -------------------------------------------------------------------------------- 1 | getConfiguration(); 25 | return !$moduleConfiguration->exposeGlobalFieldsInGraphQLSchema(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ObjectModels/SchemaDefinitionReferenceObjectInterface.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | public function getSchemaDefinitionPath(): array; 13 | 14 | public function getID(): string; 15 | } 16 | -------------------------------------------------------------------------------- /src/ObjectModels/SchemaExtensions.php: -------------------------------------------------------------------------------- 1 | schemaDefinition[SchemaDefinition::SCHEMA_IS_NAMESPACED] ?? false; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ObjectModels/TypeInterface.php: -------------------------------------------------------------------------------- 1 | mandatoryOperationDirectiveResolvers[] = $directiveResolver; 19 | } 20 | /** 21 | * @return FieldDirectiveResolverInterface[] 22 | */ 23 | public function getMandatoryOperationDirectiveResolvers(): array 24 | { 25 | return $this->mandatoryOperationDirectiveResolvers; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Registries/MandatoryOperationDirectiveResolverRegistryInterface.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | public function &getFullSchemaDefinitionForGraphQL(): array; 17 | public function registerSchemaDefinitionReferenceObject( 18 | SchemaDefinitionReferenceObjectInterface $referenceObject 19 | ): string; 20 | public function getSchemaDefinitionReferenceObject( 21 | string $referenceObjectID 22 | ): ?SchemaDefinitionReferenceObjectInterface; 23 | } 24 | -------------------------------------------------------------------------------- /src/RelationalTypeDataLoaders/ObjectType/MutationRootObjectTypeDataLoader.php: -------------------------------------------------------------------------------- 1 | mutationRoot === null) { 17 | /** @var MutationRoot */ 18 | $mutationRoot = $this->instanceManager->getInstance(MutationRoot::class); 19 | $this->mutationRoot = $mutationRoot; 20 | } 21 | return $this->mutationRoot; 22 | } 23 | 24 | /** 25 | * @param array $ids 26 | * @return array 27 | */ 28 | public function getObjects(array $ids): array 29 | { 30 | return [ 31 | $this->getMutationRoot(), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/RelationalTypeDataLoaders/ObjectType/QueryRootObjectTypeDataLoader.php: -------------------------------------------------------------------------------- 1 | queryRoot === null) { 17 | /** @var QueryRoot */ 18 | $queryRoot = $this->instanceManager->getInstance(QueryRoot::class); 19 | $this->queryRoot = $queryRoot; 20 | } 21 | return $this->queryRoot; 22 | } 23 | 24 | /** 25 | * @param array $ids 26 | * @return array 27 | */ 28 | public function getObjects(array $ids): array 29 | { 30 | return [ 31 | $this->getQueryRoot(), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/RelationalTypeDataLoaders/ObjectType/SchemaDefinitionReferenceObjectTypeDataLoader.php: -------------------------------------------------------------------------------- 1 | schemaDefinitionReferenceRegistry === null) { 17 | /** @var SchemaDefinitionReferenceRegistryInterface */ 18 | $schemaDefinitionReferenceRegistry = $this->instanceManager->getInstance(SchemaDefinitionReferenceRegistryInterface::class); 19 | $this->schemaDefinitionReferenceRegistry = $schemaDefinitionReferenceRegistry; 20 | } 21 | return $this->schemaDefinitionReferenceRegistry; 22 | } 23 | 24 | /** 25 | * @param array $ids 26 | * @return array 27 | */ 28 | public function getObjects(array $ids): array 29 | { 30 | /** @var string[] $ids */ 31 | return array_map( 32 | $this->getSchemaDefinitionReferenceRegistry()->getSchemaDefinitionReferenceObject(...), 33 | $ids 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/RelationalTypeDataLoaders/ObjectType/SchemaObjectTypeDataLoader.php: -------------------------------------------------------------------------------- 1 | schemaObjectTypeResolver === null) { 22 | /** @var SchemaObjectTypeResolver */ 23 | $schemaObjectTypeResolver = $this->instanceManager->getInstance(SchemaObjectTypeResolver::class); 24 | $this->schemaObjectTypeResolver = $schemaObjectTypeResolver; 25 | } 26 | return $this->schemaObjectTypeResolver; 27 | } 28 | final protected function getSchemaDefinitionReferenceRegistry(): SchemaDefinitionReferenceRegistryInterface 29 | { 30 | if ($this->schemaDefinitionReferenceRegistry === null) { 31 | /** @var SchemaDefinitionReferenceRegistryInterface */ 32 | $schemaDefinitionReferenceRegistry = $this->instanceManager->getInstance(SchemaDefinitionReferenceRegistryInterface::class); 33 | $this->schemaDefinitionReferenceRegistry = $schemaDefinitionReferenceRegistry; 34 | } 35 | return $this->schemaDefinitionReferenceRegistry; 36 | } 37 | 38 | public function getObjectTypeResolver(): ObjectTypeResolverInterface 39 | { 40 | return $this->getSchemaObjectTypeResolver(); 41 | } 42 | 43 | protected function getObjectTypeNewInstance(int|string $id): mixed 44 | { 45 | if ($id !== Schema::ID) { 46 | throw new ShouldNotHappenException(sprintf( 47 | $this->__('The Schema object data must be unique, so must not create object with ID "%s"', 'gatographql'), 48 | $id 49 | )); 50 | } 51 | 52 | $fullSchemaDefinition = $this->getSchemaDefinitionReferenceRegistry()->getFullSchemaDefinitionForGraphQL(); 53 | return new Schema( 54 | $fullSchemaDefinition, 55 | (string) $id 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Schema/GraphQLSchemaDefinitionServiceInterface.php: -------------------------------------------------------------------------------- 1 | appThread = $this->initializeApp(); 32 | App::setAppThread($currentAppThread); 33 | } 34 | 35 | abstract protected function initializeApp(): AppThreadInterface; 36 | 37 | /** 38 | * The basic state for executing GraphQL queries is already set. 39 | * In addition, inject the actual GraphQL query and variables, 40 | * build the AST, and generate and print the data. 41 | * 42 | * @param array $variables 43 | */ 44 | public function execute( 45 | string|ExecutableDocument $queryOrExecutableDocument, 46 | array $variables = [], 47 | ?string $operationName = null 48 | ): Response { 49 | /** 50 | * Keep the current AppThread, switch to the GraphQLServer's 51 | * one, resolve the query, and then restore the current AppThread. 52 | */ 53 | $currentAppThread = App::getAppThread(); 54 | App::setAppThread($this->appThread); 55 | 56 | /** 57 | * Because an "internal" request may be triggered 58 | * while resolving another "internal" request, 59 | * backup and then restore the App's state. 60 | */ 61 | $appStateManager = App::getAppStateManager(); 62 | $appState = $appStateManager->getAppState(); 63 | 64 | $response = parent::execute( 65 | $queryOrExecutableDocument, 66 | $variables, 67 | $operationName, 68 | ); 69 | 70 | // Restore the App's state 71 | $appStateManager->setAppState($appState); 72 | 73 | // Restore the original AppThread 74 | App::setAppThread($currentAppThread); 75 | 76 | return $response; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Server/GraphQLServerInterface.php: -------------------------------------------------------------------------------- 1 | "application/json") 15 | * 16 | * @param array $variables 17 | */ 18 | public function execute( 19 | string|ExecutableDocument $queryOrExecutableDocument, 20 | array $variables = [], 21 | ?string $operationName = null 22 | ): Response; 23 | } 24 | -------------------------------------------------------------------------------- /src/State/AppStateProvider.php: -------------------------------------------------------------------------------- 1 | graphQLDataStructureFormatter === null) { 20 | /** @var GraphQLDataStructureFormatter */ 21 | $graphQLDataStructureFormatter = $this->instanceManager->getInstance(GraphQLDataStructureFormatter::class); 22 | $this->graphQLDataStructureFormatter = $graphQLDataStructureFormatter; 23 | } 24 | return $this->graphQLDataStructureFormatter; 25 | } 26 | 27 | /** 28 | * @param array $state 29 | */ 30 | public function execute(array &$state): void 31 | { 32 | /** 33 | * Call ModuleConfiguration only after hooks from 34 | * SchemaConfigurationExecuter have been initialized. 35 | * That's why these are called on `execute` and not `initialize`. 36 | * 37 | * @var ModuleConfiguration 38 | */ 39 | $moduleConfiguration = App::getModule(Module::class)->getConfiguration(); 40 | $state['graphql-introspection-enabled'] = $moduleConfiguration->enableGraphQLIntrospection() ?? true; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Syntax/GraphQLSyntaxService.php: -------------------------------------------------------------------------------- 1 | getConfiguration(); 29 | return array_merge( 30 | [ 31 | DirectiveKinds::QUERY, 32 | DirectiveKinds::SCHEMA, 33 | ], 34 | $moduleConfiguration->enableComposableDirectives() ? [ 35 | DirectiveKinds::INDEXING, 36 | ] : [], 37 | ); 38 | } 39 | 40 | /** 41 | * Convert the DirectiveKind enum from UPPERCASE as input, to lowercase 42 | * as defined in DirectiveKinds.php 43 | */ 44 | public function coerceValue( 45 | string|int|float|bool|stdClass $inputValue, 46 | AstInterface $astNode, 47 | ObjectTypeFieldResolutionFeedbackStore $objectTypeFieldResolutionFeedbackStore, 48 | ): string|int|float|bool|object|null { 49 | // Validate type first 50 | if (!is_string($inputValue)) { 51 | return parent::coerceValue($inputValue, $astNode, $objectTypeFieldResolutionFeedbackStore); 52 | } 53 | return parent::coerceValue(strtolower($inputValue), $astNode, $objectTypeFieldResolutionFeedbackStore); 54 | } 55 | 56 | /** 57 | * Convert back from lowercase to UPPERCASE 58 | * 59 | * @return string|int|float|bool|mixed[]|stdClass 60 | */ 61 | public function serialize(string|int|float|bool|object $scalarValue): string|int|float|bool|array|stdClass 62 | { 63 | /** @var string $scalarValue */ 64 | return strtoupper($scalarValue); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/TypeResolvers/EnumType/DirectiveLocationEnumTypeResolver.php: -------------------------------------------------------------------------------- 1 | getConfiguration(); 51 | if (!$moduleConfiguration->exposeSchemaTypeDirectiveLocations()) { 52 | return $queryTypeDirectiveLocations; 53 | } 54 | 55 | /** 56 | * All the enums below are "Schema Type", 57 | * also called TypeSystemDirectiveLocation 58 | * 59 | * @see https://spec.graphql.org/draft/#TypeSystemDirectiveLocation 60 | */ 61 | $schemaTypeDirectiveLocations = [ 62 | DirectiveLocations::SCHEMA, 63 | DirectiveLocations::SCALAR, 64 | DirectiveLocations::OBJECT, 65 | DirectiveLocations::FIELD_DEFINITION, 66 | DirectiveLocations::ARGUMENT_DEFINITION, 67 | DirectiveLocations::INTERFACE, 68 | DirectiveLocations::UNION, 69 | DirectiveLocations::ENUM, 70 | DirectiveLocations::ENUM_VALUE, 71 | DirectiveLocations::INPUT_OBJECT, 72 | DirectiveLocations::INPUT_FIELD_DEFINITION, 73 | ]; 74 | return [ 75 | ...$queryTypeDirectiveLocations, 76 | ...$schemaTypeDirectiveLocations 77 | ]; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/TypeResolvers/EnumType/TypeKindEnumTypeResolver.php: -------------------------------------------------------------------------------- 1 | rootObjectTypeResolver === null) { 22 | /** @var RootObjectTypeResolver */ 23 | $rootObjectTypeResolver = $this->instanceManager->getInstance(RootObjectTypeResolver::class); 24 | $this->rootObjectTypeResolver = $rootObjectTypeResolver; 25 | } 26 | return $this->rootObjectTypeResolver; 27 | } 28 | 29 | protected function getTypeResolverToCalculateSchema(): RelationalTypeResolverInterface 30 | { 31 | return $this->getRootObjectTypeResolver(); 32 | } 33 | 34 | protected function isFieldNameResolvedByObjectTypeFieldResolver( 35 | ObjectTypeResolverInterface | InterfaceTypeResolverInterface $objectTypeOrInterfaceTypeResolver, 36 | ObjectTypeFieldResolverInterface | InterfaceTypeFieldResolverInterface $objectTypeOrInterfaceTypeFieldResolver, 37 | string $fieldName 38 | ): bool { 39 | if ( 40 | $objectTypeOrInterfaceTypeFieldResolver instanceof ObjectTypeFieldResolverInterface 41 | && !$this->isFieldNameConditionSatisfiedForSchema($objectTypeOrInterfaceTypeFieldResolver, $fieldName) 42 | ) { 43 | return false; 44 | } 45 | return parent::isFieldNameResolvedByObjectTypeFieldResolver( 46 | $objectTypeOrInterfaceTypeResolver, 47 | $objectTypeOrInterfaceTypeFieldResolver, 48 | $fieldName 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/DirectiveExtensionsObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | __('Extensions (custom metadata) added to the directive', 'graphql-server'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/DirectiveObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | schemaDefinitionReferenceObjectTypeDataLoader === null) { 18 | /** @var SchemaDefinitionReferenceObjectTypeDataLoader */ 19 | $schemaDefinitionReferenceObjectTypeDataLoader = $this->instanceManager->getInstance(SchemaDefinitionReferenceObjectTypeDataLoader::class); 20 | $this->schemaDefinitionReferenceObjectTypeDataLoader = $schemaDefinitionReferenceObjectTypeDataLoader; 21 | } 22 | return $this->schemaDefinitionReferenceObjectTypeDataLoader; 23 | } 24 | 25 | public function getTypeName(): string 26 | { 27 | return '__Directive'; 28 | } 29 | 30 | public function getTypeDescription(): ?string 31 | { 32 | return $this->__('A GraphQL directive in the data graph', 'graphql-server'); 33 | } 34 | 35 | public function getID(object $object): string|int|null 36 | { 37 | /** @var Directive */ 38 | $directive = $object; 39 | return $directive->getID(); 40 | } 41 | 42 | public function getRelationalTypeDataLoader(): RelationalTypeDataLoaderInterface 43 | { 44 | return $this->getSchemaDefinitionReferenceObjectTypeDataLoader(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/EnumValueExtensionsObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | __('Extensions (custom metadata) added to the enum value', 'graphql-server'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/EnumValueObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | schemaDefinitionReferenceObjectTypeDataLoader === null) { 18 | /** @var SchemaDefinitionReferenceObjectTypeDataLoader */ 19 | $schemaDefinitionReferenceObjectTypeDataLoader = $this->instanceManager->getInstance(SchemaDefinitionReferenceObjectTypeDataLoader::class); 20 | $this->schemaDefinitionReferenceObjectTypeDataLoader = $schemaDefinitionReferenceObjectTypeDataLoader; 21 | } 22 | return $this->schemaDefinitionReferenceObjectTypeDataLoader; 23 | } 24 | 25 | public function getTypeName(): string 26 | { 27 | return '__EnumValue'; 28 | } 29 | 30 | public function getTypeDescription(): ?string 31 | { 32 | return $this->__('Representation of an Enum value in GraphQL', 'graphql-server'); 33 | } 34 | 35 | public function getID(object $object): string|int|null 36 | { 37 | /** @var EnumValue */ 38 | $enumValue = $object; 39 | return $enumValue->getID(); 40 | } 41 | 42 | public function getRelationalTypeDataLoader(): RelationalTypeDataLoaderInterface 43 | { 44 | return $this->getSchemaDefinitionReferenceObjectTypeDataLoader(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/FieldExtensionsObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | __('Extensions (custom metadata) added to the field', 'graphql-server'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/FieldObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | schemaDefinitionReferenceObjectTypeDataLoader === null) { 18 | /** @var SchemaDefinitionReferenceObjectTypeDataLoader */ 19 | $schemaDefinitionReferenceObjectTypeDataLoader = $this->instanceManager->getInstance(SchemaDefinitionReferenceObjectTypeDataLoader::class); 20 | $this->schemaDefinitionReferenceObjectTypeDataLoader = $schemaDefinitionReferenceObjectTypeDataLoader; 21 | } 22 | return $this->schemaDefinitionReferenceObjectTypeDataLoader; 23 | } 24 | 25 | public function getTypeName(): string 26 | { 27 | return '__Field'; 28 | } 29 | 30 | public function getTypeDescription(): ?string 31 | { 32 | return $this->__('Representation of a GraphQL type\'s field', 'graphql-server'); 33 | } 34 | 35 | public function getID(object $object): string|int|null 36 | { 37 | /** @var Field */ 38 | $field = $object; 39 | return $field->getID(); 40 | } 41 | 42 | public function getRelationalTypeDataLoader(): RelationalTypeDataLoaderInterface 43 | { 44 | return $this->getSchemaDefinitionReferenceObjectTypeDataLoader(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/InputValueExtensionsObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | __('Extensions (custom metadata) added to the input value', 'graphql-server'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/InputValueObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | schemaDefinitionReferenceObjectTypeDataLoader === null) { 18 | /** @var SchemaDefinitionReferenceObjectTypeDataLoader */ 19 | $schemaDefinitionReferenceObjectTypeDataLoader = $this->instanceManager->getInstance(SchemaDefinitionReferenceObjectTypeDataLoader::class); 20 | $this->schemaDefinitionReferenceObjectTypeDataLoader = $schemaDefinitionReferenceObjectTypeDataLoader; 21 | } 22 | return $this->schemaDefinitionReferenceObjectTypeDataLoader; 23 | } 24 | 25 | public function getTypeName(): string 26 | { 27 | return '__InputValue'; 28 | } 29 | 30 | public function getTypeDescription(): ?string 31 | { 32 | return $this->__('Representation of an input object in GraphQL', 'graphql-server'); 33 | } 34 | 35 | public function getID(object $object): string|int|null 36 | { 37 | /** @var InputValue */ 38 | $inputValue = $object; 39 | return $inputValue->getID(); 40 | } 41 | 42 | public function getRelationalTypeDataLoader(): RelationalTypeDataLoaderInterface 43 | { 44 | return $this->getSchemaDefinitionReferenceObjectTypeDataLoader(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/NamedTypeExtensionsObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | __('Extensions (custom metadata) added to the GraphQL type (for all \'named\' types: Object, Interface, Union, Scalar, Enum and InputObject)', 'graphql-server'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/QueryRootObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | queryRootObjectTypeDataLoader === null) { 22 | /** @var QueryRootObjectTypeDataLoader */ 23 | $queryRootObjectTypeDataLoader = $this->instanceManager->getInstance(QueryRootObjectTypeDataLoader::class); 24 | $this->queryRootObjectTypeDataLoader = $queryRootObjectTypeDataLoader; 25 | } 26 | return $this->queryRootObjectTypeDataLoader; 27 | } 28 | 29 | public function getTypeName(): string 30 | { 31 | return 'QueryRoot'; 32 | } 33 | 34 | public function getTypeDescription(): ?string 35 | { 36 | return $this->__('Query type, starting from which the query is executed', 'graphql-server'); 37 | } 38 | 39 | public function getID(object $object): string|int|null 40 | { 41 | /** @var QueryRoot */ 42 | $queryRoot = $object; 43 | return $queryRoot->getID(); 44 | } 45 | 46 | public function getRelationalTypeDataLoader(): RelationalTypeDataLoaderInterface 47 | { 48 | return $this->getQueryRootObjectTypeDataLoader(); 49 | } 50 | 51 | public function isFieldNameConditionSatisfiedForSchema( 52 | ObjectTypeFieldResolverInterface $objectTypeFieldResolver, 53 | string $fieldName 54 | ): bool { 55 | return 56 | // Fields "queryRoot" and "mutationRoot" are helpers, must not be ported to QueryRoot 57 | !in_array($fieldName, ['queryRoot', 'mutationRoot']) 58 | && $objectTypeFieldResolver->getFieldMutationResolver($this, $fieldName) === null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/SchemaExtensionsObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | __('Extensions (custom metadata) added to the GraphQL schema', 'graphql-server'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/SchemaObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | schemaObjectTypeDataLoader === null) { 18 | /** @var SchemaObjectTypeDataLoader */ 19 | $schemaObjectTypeDataLoader = $this->instanceManager->getInstance(SchemaObjectTypeDataLoader::class); 20 | $this->schemaObjectTypeDataLoader = $schemaObjectTypeDataLoader; 21 | } 22 | return $this->schemaObjectTypeDataLoader; 23 | } 24 | 25 | public function getTypeName(): string 26 | { 27 | return '__Schema'; 28 | } 29 | 30 | public function getTypeDescription(): ?string 31 | { 32 | return $this->__('Schema type, to implement the introspection fields', 'graphql-server'); 33 | } 34 | 35 | public function getID(object $object): string|int|null 36 | { 37 | /** @var Schema */ 38 | $schema = $object; 39 | return $schema->getID(); 40 | } 41 | 42 | public function getRelationalTypeDataLoader(): RelationalTypeDataLoaderInterface 43 | { 44 | return $this->getSchemaObjectTypeDataLoader(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/TypeObjectTypeResolver.php: -------------------------------------------------------------------------------- 1 | wrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader === null) { 18 | /** @var WrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader */ 19 | $wrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader = $this->instanceManager->getInstance(WrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader::class); 20 | $this->wrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader = $wrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader; 21 | } 22 | return $this->wrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader; 23 | } 24 | 25 | public function getTypeName(): string 26 | { 27 | return '__Type'; 28 | } 29 | 30 | public function getTypeDescription(): ?string 31 | { 32 | return $this->__('Representation of each GraphQL type in the graph', 'graphql-server'); 33 | } 34 | 35 | public function getID(object $object): string|int|null 36 | { 37 | /** @var TypeInterface */ 38 | $type = $object; 39 | return $type->getID(); 40 | } 41 | 42 | public function getRelationalTypeDataLoader(): RelationalTypeDataLoaderInterface 43 | { 44 | return $this->getWrappingTypeOrSchemaDefinitionReferenceObjectTypeDataLoader(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TypeResolvers/ObjectType/UseRootAsSourceForSchemaObjectTypeResolverInterface.php: -------------------------------------------------------------------------------- 1 | ,array> 18 | */ 19 | protected static function getGraphQLServerModuleClassConfiguration(): array 20 | { 21 | return [ 22 | ...parent::getGraphQLServerModuleClassConfiguration(), 23 | ...[ 24 | \PoP\ComponentModel\Module::class => [ 25 | \PoP\ComponentModel\Environment::CONVERT_INPUT_VALUE_FROM_SINGLE_TO_LIST => static::isEnabled(), 26 | ], 27 | ] 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Unit/AbstractEnabledDisabledFixtureQueryExecutionGraphQLServerTestCase.php: -------------------------------------------------------------------------------- 1 | ,array> 18 | */ 19 | protected static function getGraphQLServerModuleClassConfiguration(): array 20 | { 21 | return [ 22 | ...parent::getGraphQLServerModuleClassConfiguration(), 23 | ...[ 24 | \GraphQLByPoP\GraphQLServer\Module::class => [ 25 | \GraphQLByPoP\GraphQLServer\Environment::EXPOSE_GLOBAL_FIELDS_IN_GRAPHQL_SCHEMA => static::isEnabled(), 26 | ], 27 | ] 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Unit/AbstractOrderedFieldsFixtureQueryExecutionGraphQLServerTestCase.php: -------------------------------------------------------------------------------- 1 | assertSame( 21 | json_encode(json_decode($fileContents), JSON_PRETTY_PRINT), 22 | json_encode(json_decode($actualResponseContent), JSON_PRETTY_PRINT) 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Unit/AbstractQueryExecutionGraphQLServerTestCase.php: -------------------------------------------------------------------------------- 1 | $variables 12 | */ 13 | #[\PHPUnit\Framework\Attributes\DataProvider('graphQLServerExecutionProvider')] 14 | public function testGraphQLServerExecution(string $query, array $expectedResponse, array $variables = [], ?string $operationName = null): void 15 | { 16 | $this->assertGraphQLQueryExecution($query, $expectedResponse, $variables, $operationName); 17 | } 18 | 19 | /** 20 | * @return mixed[] 21 | */ 22 | abstract public static function graphQLServerExecutionProvider(): array; 23 | } 24 | -------------------------------------------------------------------------------- /tests/Unit/DisabledConvertInputValueFromSingleToListFixtureQueryExecutionGraphQLServerTest.php: -------------------------------------------------------------------------------- 1 | getFileState(); 20 | // return $filePath . \DIRECTORY_SEPARATOR . $fileName . '@' . $state . '.var.json'; 21 | // } 22 | 23 | protected static function getFileState(): string 24 | { 25 | return static::isEnabled() ? 'enabled' : 'disabled'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Unit/EnabledExposeGlobalFieldsInGraphQLSchemaFixtureQueryExecutionGraphQLServerTest.php: -------------------------------------------------------------------------------- 1 | ,array> 21 | */ 22 | protected static function getGraphQLServerModuleClassConfiguration(): array 23 | { 24 | return [ 25 | ...parent::getGraphQLServerModuleClassConfiguration(), 26 | ...[ 27 | \PoP\ComponentModel\Module::class => [ 28 | \PoP\ComponentModel\Environment::EXPOSE_CORE_FUNCTIONALITY_GLOBAL_FIELDS => true, 29 | ], 30 | ] 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Unit/FixtureQueryExecutionGraphQLServerTestCaseTrait.php: -------------------------------------------------------------------------------- 1 | in($directory)->files()->name($fileNames)->notName($notFileNames); 35 | // Allow fixtures to be named with cardinal numbers, to execute the tests in a desired order 36 | $finder->sortByName(true); 37 | $fileInfos = iterator_to_array($finder); 38 | return array_values($fileInfos); 39 | } 40 | 41 | /** 42 | * @throws RuntimeException 43 | */ 44 | protected static function throwFileNotExistsException(string $file): void 45 | { 46 | throw new RuntimeException( 47 | sprintf( 48 | 'File "%s" does not exist', 49 | $file 50 | ) 51 | ); 52 | } 53 | 54 | /** 55 | * Since PHPUnit v10, this is not possible anymore! 56 | */ 57 | // protected function addFixtureFolderInfo(string $string): string 58 | // { 59 | // return sprintf( 60 | // ' (fixture folder: "%s")%s', 61 | // static::getResponseFixtureFolder(), 62 | // $string, 63 | // ); 64 | // } 65 | } 66 | -------------------------------------------------------------------------------- /tests/Unit/NamespacingFixtureQueryExecutionGraphQLServerTest.php: -------------------------------------------------------------------------------- 1 | ,array> 21 | */ 22 | protected static function getGraphQLServerModuleClassConfiguration(): array 23 | { 24 | return [ 25 | ...parent::getGraphQLServerModuleClassConfiguration(), 26 | ...[ 27 | \PoP\ComponentModel\Module::class => [ 28 | \PoP\ComponentModel\Environment::NAMESPACE_TYPES_AND_INTERFACES => true, 29 | ], 30 | ] 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Unit/OrderedFieldsFixtureQueryExecutionGraphQLServerTest.php: -------------------------------------------------------------------------------- 1 | [ 18 | ' 19 | { 20 | id 21 | } 22 | ', 23 | [ 24 | 'data' => [ 25 | 'id' => Root::ID, 26 | ] 27 | ] 28 | ], 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/Unit/Upstream/ComponentModel/InputValueCoercionQueryExecutionGraphQLServerTest.php: -------------------------------------------------------------------------------- 1 | [ 18 | ' 19 | query Echo($include: Boolean!) { 20 | id @include(if: $include) 21 | } 22 | ', 23 | [ 24 | "errors" => [ 25 | [ 26 | "message" => "Argument 'if' of type 'Boolean' cannot be an object", 27 | "locations" => [ 28 | [ 29 | "line" => 3, 30 | "column" => 37 31 | ] 32 | ], 33 | "extensions" => [ 34 | "path" => [ 35 | "\$include", 36 | "(if: \$include)", 37 | "@include(if: \$include)", 38 | "id @include(if: \$include)", 39 | "query Echo(\$include: Boolean!) { ... }" 40 | ], 41 | "type" => "QueryRoot", 42 | "field" => "id @include(if: \$include)", 43 | "code" => "gql@5.6.1[20]", 44 | "specifiedBy" => "https://spec.graphql.org/draft/#sec-Values-of-Correct-Type" 45 | ] 46 | ] 47 | ], 48 | "data" => [ 49 | "id" => null 50 | ] 51 | ], 52 | // Pass any non-stdClass object here 53 | [ 54 | 'include' => static::getGraphQLServer(), 55 | ] 56 | ], 57 | ]; 58 | foreach ($items as $item) { 59 | [$query, $expectedResponse, $variables] = $item; 60 | $this->assertGraphQLQueryExecution($query, $expectedResponse, $variables); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/Unit/Upstream/ComponentModel/VariablesQueryExecutionGraphQLServerTest.php: -------------------------------------------------------------------------------- 1 | [ 19 | ' 20 | query Echo($include: Boolean!, $skip: Boolean!) { 21 | id @include(if: $include) 22 | again: id @skip(if: $skip) 23 | } 24 | ', 25 | [ 26 | 'data' => [ 27 | 'id' => "root", 28 | ], 29 | ], 30 | [ 31 | 'include' => true, 32 | 'skip' => true, 33 | ] 34 | ], 35 | 'var-not-defined' => [ 36 | ' 37 | query Echo { 38 | id @include(if: $include) 39 | } 40 | ', 41 | [ 42 | 'errors' => [ 43 | [ 44 | 'extensions' => [ 45 | 'code' => $feedbackItemResolution->getNamespacedCode(), 46 | 'path' => [ 47 | '$include', 48 | '(if: $include)', 49 | '@include(if: $include)', 50 | 'id @include(if: $include)', 51 | 'query Echo { ... }', 52 | ], 53 | 'specifiedBy' => $feedbackItemResolution->getSpecifiedByURL() 54 | ], 55 | 'locations' => [ 56 | (new Location(3, 37))->toArray() 57 | ], 58 | 'message' => $feedbackItemResolution->getMessage(), 59 | ], 60 | ], 61 | ], 62 | ], 63 | ]; 64 | foreach ($items as $item) { 65 | $item[2] ??= []; 66 | [$query, $expectedResponse, $variables] = $item; 67 | $this->assertGraphQLQueryExecution($query, $expectedResponse, $variables); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/Unit/fixture-convert-input-value-from-single-to-list/array-input-passed-as-single-value.gql: -------------------------------------------------------------------------------- 1 | query { 2 | __schema { 3 | directives(ofKinds: "query") { 4 | name 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-convert-input-value-from-single-to-list/array-input-passed-as-single-value@disabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Argument 'ofKinds' expects an array, but value 'query' was provided", 5 | "locations": [ 6 | { 7 | "line": 3, 8 | "column": 26 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "\"query\"", 14 | "(ofKinds: \"query\")", 15 | "directives(ofKinds: \"query\") { ... }", 16 | "__schema { ... }", 17 | "query { ... }" 18 | ], 19 | "type": "__Schema", 20 | "field": "directives(ofKinds: \"query\") { ... }", 21 | "code": "gql@5.6.1[9]", 22 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Values-of-Correct-Type" 23 | } 24 | } 25 | ], 26 | "data": { 27 | "__schema": { 28 | "directives": null 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-convert-input-value-from-single-to-list/array-input-passed-as-single-value@enabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "__schema": { 4 | "directives": [ 5 | { 6 | "name": "include" 7 | }, 8 | { 9 | "name": "skip" 10 | } 11 | ] 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-expose-global-fields-in-graphql-schema/introspection-global-fields.gql: -------------------------------------------------------------------------------- 1 | query IntrospectionGlobalFields { 2 | __schema { 3 | globalFields { 4 | name 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/Unit/fixture-expose-global-fields-in-graphql-schema/introspection-global-fields@disabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "There is no field 'globalFields' on type '__Schema'", 5 | "locations": [ 6 | { 7 | "line": 3, 8 | "column": 9 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "globalFields { ... }", 14 | "__schema { ... }", 15 | "query IntrospectionGlobalFields { ... }" 16 | ], 17 | "type": "__Schema", 18 | "field": "globalFields { ... }", 19 | "code": "gql@5.3.1", 20 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 21 | } 22 | } 23 | ], 24 | "data": { 25 | "__schema": { 26 | "globalFields": null 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-expose-global-fields-in-graphql-schema/introspection-global-fields@enabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "__schema": { 4 | "globalFields": [ 5 | { 6 | "name": "_namespace" 7 | }, 8 | { 9 | "name": "_qualifiedTypeName" 10 | }, 11 | { 12 | "name": "_typeName" 13 | } 14 | ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-expose-global-fields-in-graphql-schema/introspection-query.gql: -------------------------------------------------------------------------------- 1 | query IntrospectionQuery { 2 | __schema { 3 | queryType { 4 | name 5 | } 6 | mutationType { 7 | name 8 | } 9 | subscriptionType { 10 | name 11 | } 12 | types { 13 | ...FullType 14 | } 15 | directives { 16 | name 17 | description 18 | locations 19 | args { 20 | ...InputValue 21 | } 22 | } 23 | } 24 | } 25 | 26 | fragment FullType on __Type { 27 | kind 28 | name 29 | description 30 | fields(includeDeprecated: true) { 31 | name 32 | description 33 | args { 34 | ...InputValue 35 | } 36 | type { 37 | ...TypeRef 38 | } 39 | isDeprecated 40 | deprecationReason 41 | } 42 | inputFields { 43 | ...InputValue 44 | } 45 | interfaces { 46 | ...TypeRef 47 | } 48 | enumValues(includeDeprecated: true) { 49 | name 50 | description 51 | isDeprecated 52 | deprecationReason 53 | } 54 | possibleTypes { 55 | ...TypeRef 56 | } 57 | } 58 | 59 | fragment InputValue on __InputValue { 60 | name 61 | description 62 | type { 63 | ...TypeRef 64 | } 65 | defaultValue 66 | } 67 | 68 | fragment TypeRef on __Type { 69 | kind 70 | name 71 | ofType { 72 | kind 73 | name 74 | ofType { 75 | kind 76 | name 77 | ofType { 78 | kind 79 | name 80 | ofType { 81 | kind 82 | name 83 | ofType { 84 | kind 85 | name 86 | ofType { 87 | kind 88 | name 89 | ofType { 90 | kind 91 | name 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-expose-global-fields-in-graphql-schema/introspection-type-global-fields.gql: -------------------------------------------------------------------------------- 1 | query IntrospectionFieldArgGlobalFields { 2 | __schema { 3 | type(name: "QueryRoot") { 4 | fields(includeGlobal: true) { 5 | name 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/Unit/fixture-expose-global-fields-in-graphql-schema/introspection-type-global-fields@disabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "On field 'fields' of type '__Type', there is no argument with name 'includeGlobal'", 5 | "locations": [ 6 | { 7 | "line": 4, 8 | "column": 20 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "(includeGlobal: true)", 14 | "fields(includeGlobal: true) { ... }", 15 | "type(name: \"QueryRoot\") { ... }", 16 | "__schema { ... }", 17 | "query IntrospectionFieldArgGlobalFields { ... }" 18 | ], 19 | "type": "__Type", 20 | "field": "fields(includeGlobal: true) { ... }", 21 | "code": "gql@5.4.1[a]", 22 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Argument-Names" 23 | } 24 | } 25 | ], 26 | "data": { 27 | "__schema": { 28 | "type": { 29 | "fields": null 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-expose-global-fields-in-graphql-schema/introspection-type-global-fields@enabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "__schema": { 4 | "type": { 5 | "fields": [ 6 | { 7 | "name": "globalID" 8 | }, 9 | { 10 | "name": "id" 11 | }, 12 | { 13 | "name": "self" 14 | }, 15 | { 16 | "name": "_namespace" 17 | }, 18 | { 19 | "name": "_qualifiedTypeName" 20 | }, 21 | { 22 | "name": "_typeName" 23 | } 24 | ] 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-namespacing/introspection-query.gql: -------------------------------------------------------------------------------- 1 | query IntrospectionQuery { 2 | __schema { 3 | queryType { 4 | name 5 | } 6 | mutationType { 7 | name 8 | } 9 | subscriptionType { 10 | name 11 | } 12 | types { 13 | ...FullType 14 | } 15 | directives { 16 | name 17 | description 18 | locations 19 | args { 20 | ...InputValue 21 | } 22 | } 23 | } 24 | } 25 | 26 | fragment FullType on __Type { 27 | kind 28 | name 29 | description 30 | fields(includeDeprecated: true) { 31 | name 32 | description 33 | args { 34 | ...InputValue 35 | } 36 | type { 37 | ...TypeRef 38 | } 39 | isDeprecated 40 | deprecationReason 41 | } 42 | inputFields { 43 | ...InputValue 44 | } 45 | interfaces { 46 | ...TypeRef 47 | } 48 | enumValues(includeDeprecated: true) { 49 | name 50 | description 51 | isDeprecated 52 | deprecationReason 53 | } 54 | possibleTypes { 55 | ...TypeRef 56 | } 57 | } 58 | 59 | fragment InputValue on __InputValue { 60 | name 61 | description 62 | type { 63 | ...TypeRef 64 | } 65 | defaultValue 66 | } 67 | 68 | fragment TypeRef on __Type { 69 | kind 70 | name 71 | ofType { 72 | kind 73 | name 74 | ofType { 75 | kind 76 | name 77 | ofType { 78 | kind 79 | name 80 | ofType { 81 | kind 82 | name 83 | ofType { 84 | kind 85 | name 86 | ofType { 87 | kind 88 | name 89 | ofType { 90 | kind 91 | name 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-ordered-fields/error/response-entries-order.gql: -------------------------------------------------------------------------------- 1 | query { 2 | id 3 | nonExisting 4 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-ordered-fields/error/response-entries-order.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "There is no field 'nonExisting' on type 'QueryRoot'", 5 | "locations": [ 6 | { 7 | "line": 3, 8 | "column": 5 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "nonExisting", 14 | "query { ... }" 15 | ], 16 | "type": "QueryRoot", 17 | "field": "nonExisting", 18 | "code": "gql@5.3.1", 19 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 20 | } 21 | } 22 | ], 23 | "data": { 24 | "id": "root", 25 | "nonExisting": null 26 | } 27 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-ordered-fields/success/field-order.gql: -------------------------------------------------------------------------------- 1 | query { 2 | firstID: id 3 | firstSelf: self { 4 | id 5 | } 6 | secondID: id 7 | secondSelf: self { 8 | id 9 | } 10 | thirdID: id 11 | thirdSelf: self { 12 | id 13 | firstID: id 14 | firstSelf: self { 15 | id 16 | } 17 | secondID: id 18 | secondSelf: self { 19 | id 20 | } 21 | thirdID: id 22 | thirdSelf: self { 23 | id 24 | } 25 | fourthID: id 26 | fourthSelf: self { 27 | id 28 | } 29 | } 30 | fourthID: id 31 | fourthSelf: self { 32 | id 33 | firstID: id 34 | firstSelf: self { 35 | id 36 | } 37 | secondID: id 38 | secondSelf: self { 39 | id 40 | } 41 | thirdID: id 42 | thirdSelf: self { 43 | id 44 | } 45 | fourthID: id 46 | fourthSelf: self { 47 | id 48 | firstID: id 49 | firstSelf: self { 50 | id 51 | } 52 | secondID: id 53 | secondSelf: self { 54 | id 55 | } 56 | thirdID: id 57 | thirdSelf: self { 58 | id 59 | } 60 | fourthID: id 61 | fourthSelf: self { 62 | id 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /tests/Unit/fixture-ordered-fields/success/field-order.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "firstID": "root", 4 | "firstSelf": { 5 | "id": "root" 6 | }, 7 | "secondID": "root", 8 | "secondSelf": { 9 | "id": "root" 10 | }, 11 | "thirdID": "root", 12 | "thirdSelf": { 13 | "id": "root", 14 | "firstID": "root", 15 | "firstSelf": { 16 | "id": "root" 17 | }, 18 | "secondID": "root", 19 | "secondSelf": { 20 | "id": "root" 21 | }, 22 | "thirdID": "root", 23 | "thirdSelf": { 24 | "id": "root" 25 | }, 26 | "fourthID": "root", 27 | "fourthSelf": { 28 | "id": "root" 29 | } 30 | }, 31 | "fourthID": "root", 32 | "fourthSelf": { 33 | "id": "root", 34 | "firstID": "root", 35 | "firstSelf": { 36 | "id": "root" 37 | }, 38 | "secondID": "root", 39 | "secondSelf": { 40 | "id": "root" 41 | }, 42 | "thirdID": "root", 43 | "thirdSelf": { 44 | "id": "root" 45 | }, 46 | "fourthID": "root", 47 | "fourthSelf": { 48 | "id": "root", 49 | "firstID": "root", 50 | "firstSelf": { 51 | "id": "root" 52 | }, 53 | "secondID": "root", 54 | "secondSelf": { 55 | "id": "root" 56 | }, 57 | "thirdID": "root", 58 | "thirdSelf": { 59 | "id": "root" 60 | }, 61 | "fourthID": "root", 62 | "fourthSelf": { 63 | "id": "root" 64 | } 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/directive-arg-type-mismatch.gql: -------------------------------------------------------------------------------- 1 | query { 2 | # The input expects a Boolean, passing a Float/Array/InputObject 3 | withFloat: id @skip(if: 1.1) 4 | withArray: id @skip(if: [true]) 5 | withInputObject: id @skip(if: {condition: false}) 6 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/directive-arg-type-mismatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Cannot cast value '1.1' for type 'Boolean'", 5 | "locations": [ 6 | { 7 | "line": 3, 8 | "column": 27 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "1.1", 14 | "(if: 1.1)", 15 | "@skip(if: 1.1)", 16 | "withFloat: id @skip(if: 1.1)", 17 | "query { ... }" 18 | ], 19 | "type": "QueryRoot", 20 | "field": "withFloat: id @skip(if: 1.1)", 21 | "code": "gql@5.6.1[16]", 22 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Values-of-Correct-Type" 23 | } 24 | }, 25 | { 26 | "message": "Argument 'if' does not expect an array, but array '[true]' was provided", 27 | "locations": [ 28 | { 29 | "line": 4, 30 | "column": 27 31 | } 32 | ], 33 | "extensions": { 34 | "path": [ 35 | "[true]", 36 | "(if: [true])", 37 | "@skip(if: [true])", 38 | "withArray: id @skip(if: [true])", 39 | "query { ... }" 40 | ], 41 | "type": "QueryRoot", 42 | "field": "withArray: id @skip(if: [true])", 43 | "code": "gql@5.6.1[8]", 44 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Values-of-Correct-Type" 45 | } 46 | }, 47 | { 48 | "message": "An object cannot be cast to type 'Boolean'", 49 | "locations": [ 50 | { 51 | "line": 5, 52 | "column": 33 53 | } 54 | ], 55 | "extensions": { 56 | "path": [ 57 | "{condition: false}", 58 | "(if: {condition: false})", 59 | "@skip(if: {condition: false})", 60 | "withInputObject: id @skip(if: {condition: false})", 61 | "query { ... }" 62 | ], 63 | "type": "QueryRoot", 64 | "field": "withInputObject: id @skip(if: {condition: false})", 65 | "code": "gql@5.6.1[1]", 66 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Values-of-Correct-Type" 67 | } 68 | } 69 | ], 70 | "data": { 71 | "withFloat": null, 72 | "withArray": null, 73 | "withInputObject": null 74 | } 75 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/empty-query.gql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GraphQLByPoP/graphql-server/137098d077eb257c4585d0ef13551909cf2a9354/tests/Unit/fixture/error/empty-query.gql -------------------------------------------------------------------------------- /tests/Unit/fixture/error/empty-query.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "The document is empty", 5 | "extensions": { 6 | "code": "gql@6.1[c]", 7 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Executing-Requests" 8 | } 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/explicit-null-fails-mandatory-directive-arg.gql: -------------------------------------------------------------------------------- 1 | query { 2 | id @skip(if: null) 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/explicit-null-fails-mandatory-directive-arg.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Argument 'if' in directive 'skip' cannot be null", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 16 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "null", 14 | "(if: null)", 15 | "@skip(if: null)", 16 | "id @skip(if: null)", 17 | "query { ... }" 18 | ], 19 | "type": "QueryRoot", 20 | "field": "id @skip(if: null)", 21 | "code": "gql@5.4.2.1[d]", 22 | "specifiedBy": "https://spec.graphql.org/draft/#sec-Required-Arguments" 23 | } 24 | } 25 | ], 26 | "data": { 27 | "id": null 28 | } 29 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/field-arg-type-mismatch.gql: -------------------------------------------------------------------------------- 1 | query { 2 | __schema { 3 | types { 4 | name 5 | # The input expects a Boolean, passing a Float/Array/InputObject 6 | passingFloat: name(namespaced: 1.2) 7 | passingArray: name(namespaced: [false]) 8 | passingInputObject: name(namespaced: {namespaced: true}) 9 | } 10 | # The input expects an Array, passing Array 11 | passingArrayOfArrays: directives(ofKinds: [["query"]]) { 12 | name 13 | } 14 | # The input expects an Array, passing Array 15 | passingArrayOfInputObject: directives(ofKinds: [{ofKinds: "query"}]) { 16 | name 17 | } 18 | # The input does not accept NULL values 19 | passingArrayWithNullValues: directives(ofKinds: ["query", null]) { 20 | name 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/field-is-not-connection.gql: -------------------------------------------------------------------------------- 1 | { 2 | id { 3 | id 4 | } 5 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/field-is-not-connection.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Field 'id' from type 'QueryRoot' is not a connection", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 5 9 | } 10 | ], 11 | "extensions": { 12 | "type": "QueryRoot", 13 | "field": "id { ... }", 14 | "path": [ 15 | "id { ... }", 16 | "query { ... }" 17 | ], 18 | "code": "gql@5.3.3", 19 | "specifiedBy": "https://spec.graphql.org/draft/#sec-Leaf-Field-Selections" 20 | } 21 | } 22 | ], 23 | "data": { 24 | "id": null 25 | } 26 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/mandatory-directive-arg-not-provided.gql: -------------------------------------------------------------------------------- 1 | query { 2 | id @skip 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/mandatory-directive-arg-not-provided.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Mandatory argument 'if' in directive 'skip' has not been provided", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 7 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "@skip", 14 | "id @skip", 15 | "query { ... }" 16 | ], 17 | "type": "QueryRoot", 18 | "field": "id @skip", 19 | "code": "gql@5.4.2.1[c]", 20 | "specifiedBy": "https://spec.graphql.org/draft/#sec-Required-Arguments" 21 | } 22 | } 23 | ], 24 | "data": { 25 | "id": null 26 | } 27 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/mandatory-field-arg-not-provided.gql: -------------------------------------------------------------------------------- 1 | query { 2 | _implements 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/mandatory-field-arg-not-provided.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Mandatory argument 'interface' in field '_implements' of type 'QueryRoot' has not been provided", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 3 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "_implements", 14 | "query { ... }" 15 | ], 16 | "type": "QueryRoot", 17 | "field": "_implements", 18 | "code": "gql@5.4.2.1[a]", 19 | "specifiedBy": "https://spec.graphql.org/draft/#sec-Required-Arguments" 20 | } 21 | } 22 | ], 23 | "data": { 24 | "_implements": null 25 | } 26 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/missing-variables.gql: -------------------------------------------------------------------------------- 1 | query SomeQuery($include: Boolean!) { 2 | id 3 | self @include(if: $include) { 4 | id 5 | } 6 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/missing-variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Non-nullable variable 'include' has not been provided", 5 | "locations": [ 6 | { 7 | "line": 3, 8 | "column": 23 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "$include", 14 | "(if: $include)", 15 | "@include(if: $include)", 16 | "self @include(if: $include) { ... }", 17 | "query SomeQuery($include: Boolean!) { ... }" 18 | ], 19 | "code": "gql@5.8.5", 20 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-All-Variable-Usages-are-Allowed" 21 | } 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-directive-arg-provided.gql: -------------------------------------------------------------------------------- 1 | query { 2 | id @skip(if: false, unless: true) 3 | multiple: id @skip(if: false, unless: true, orOtherwise: false) 4 | self { 5 | ...SelfData 6 | ...on QueryRoot { 7 | again: id 8 | againSelf: self @skip(if: false, inInlineFragment: false) { 9 | id 10 | } 11 | } 12 | } 13 | } 14 | 15 | fragment SelfData on QueryRoot { 16 | id 17 | self @skip(if: false, inFragment: false) { 18 | id 19 | } 20 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-directive.gql: -------------------------------------------------------------------------------- 1 | query { 2 | id @nonExisting 3 | self { 4 | ...SelfData 5 | ...on QueryRoot { 6 | again: id 7 | againSelf: self @nonExistingInInlineFragment { 8 | id 9 | } 10 | } 11 | } 12 | } 13 | 14 | fragment SelfData on QueryRoot { 15 | id 16 | self @nonExistingInFragment { 17 | id 18 | } 19 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-directive.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "There is no directive with name 'nonExisting'", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 9 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "@nonExisting", 14 | "id @nonExisting", 15 | "query { ... }" 16 | ], 17 | "type": "QueryRoot", 18 | "field": "id @nonExisting", 19 | "code": "gql@5.7.1", 20 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Directives-Are-Defined" 21 | } 22 | }, 23 | { 24 | "message": "There is no directive with name 'nonExistingInFragment'", 25 | "locations": [ 26 | { 27 | "line": 16, 28 | "column": 11 29 | } 30 | ], 31 | "extensions": { 32 | "path": [ 33 | "@nonExistingInFragment", 34 | "self @nonExistingInFragment { ... }", 35 | "fragment SelfData on QueryRoot { ... }" 36 | ], 37 | "type": "QueryRoot", 38 | "field": "self @nonExistingInFragment { ... }", 39 | "code": "gql@5.7.1", 40 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Directives-Are-Defined" 41 | } 42 | }, 43 | { 44 | "message": "There is no directive with name 'nonExistingInInlineFragment'", 45 | "locations": [ 46 | { 47 | "line": 7, 48 | "column": 30 49 | } 50 | ], 51 | "extensions": { 52 | "path": [ 53 | "@nonExistingInInlineFragment", 54 | "againSelf: self @nonExistingInInlineFragment { ... }", 55 | "...on QueryRoot { ... }", 56 | "self { ... }", 57 | "query { ... }" 58 | ], 59 | "type": "QueryRoot", 60 | "field": "againSelf: self @nonExistingInInlineFragment { ... }", 61 | "code": "gql@5.7.1", 62 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Directives-Are-Defined" 63 | } 64 | } 65 | ], 66 | "data": { 67 | "id": null, 68 | "self": { 69 | "id": "root", 70 | "self": null, 71 | "again": "root", 72 | "againSelf": null 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-enum-value.gql: -------------------------------------------------------------------------------- 1 | query GetDirectives { 2 | __schema { 3 | directives(ofKinds: [NON_EXISTING]) { 4 | name 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-enum-value.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Value 'non_existing' for enum type 'DirectiveKindEnum' is not valid (the only valid values are: 'query', 'schema')", 5 | "locations": [ 6 | { 7 | "line": 3, 8 | "column": 25 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "[NON_EXISTING]", 14 | "(ofKinds: [NON_EXISTING])", 15 | "directives(ofKinds: [NON_EXISTING]) { ... }", 16 | "__schema { ... }", 17 | "query GetDirectives { ... }" 18 | ], 19 | "type": "__Schema", 20 | "field": "directives(ofKinds: [NON_EXISTING]) { ... }", 21 | "code": "gql@5.6.1[14]", 22 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Values-of-Correct-Type" 23 | } 24 | } 25 | ], 26 | "data": { 27 | "__schema": { 28 | "directives": null 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-field-arg-provided.gql: -------------------------------------------------------------------------------- 1 | query { 2 | _implements(interface: "SomeInterface", type: "DoesntMatter") 3 | multiple: _implements(interface: "SomeInterface", someType: "DoesntMatter", anotherType: "AlsoDoesntMatter") 4 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-field-arg-provided.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "On field '_implements' of type 'QueryRoot', there is no argument with name 'type'", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 43 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "(type: \"DoesntMatter\")", 14 | "_implements(interface: \"SomeInterface\", type: \"DoesntMatter\")", 15 | "query { ... }" 16 | ], 17 | "type": "QueryRoot", 18 | "field": "_implements(interface: \"SomeInterface\", type: \"DoesntMatter\")", 19 | "code": "gql@5.4.1[a]", 20 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Argument-Names" 21 | } 22 | }, 23 | { 24 | "message": "On field '_implements' of type 'QueryRoot', there is no argument with name 'someType'", 25 | "locations": [ 26 | { 27 | "line": 3, 28 | "column": 53 29 | } 30 | ], 31 | "extensions": { 32 | "path": [ 33 | "(someType: \"DoesntMatter\")", 34 | "multiple: _implements(interface: \"SomeInterface\", someType: \"DoesntMatter\", anotherType: \"AlsoDoesntMatter\")", 35 | "query { ... }" 36 | ], 37 | "type": "QueryRoot", 38 | "field": "multiple: _implements(interface: \"SomeInterface\", someType: \"DoesntMatter\", anotherType: \"AlsoDoesntMatter\")", 39 | "code": "gql@5.4.1[a]", 40 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Argument-Names" 41 | } 42 | }, 43 | { 44 | "message": "On field '_implements' of type 'QueryRoot', there is no argument with name 'anotherType'", 45 | "locations": [ 46 | { 47 | "line": 3, 48 | "column": 79 49 | } 50 | ], 51 | "extensions": { 52 | "path": [ 53 | "(anotherType: \"AlsoDoesntMatter\")", 54 | "multiple: _implements(interface: \"SomeInterface\", someType: \"DoesntMatter\", anotherType: \"AlsoDoesntMatter\")", 55 | "query { ... }" 56 | ], 57 | "type": "QueryRoot", 58 | "field": "multiple: _implements(interface: \"SomeInterface\", someType: \"DoesntMatter\", anotherType: \"AlsoDoesntMatter\")", 59 | "code": "gql@5.4.1[a]", 60 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Argument-Names" 61 | } 62 | } 63 | ], 64 | "data": { 65 | "_implements": null, 66 | "multiple": null 67 | } 68 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-field.gql: -------------------------------------------------------------------------------- 1 | query { 2 | nonExisting 3 | self { 4 | ...SelfData 5 | ...on QueryRoot { 6 | nonExistingInInlineFragment 7 | } 8 | } 9 | } 10 | 11 | fragment SelfData on QueryRoot { 12 | nonExistingInFragment 13 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-field.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "There is no field 'nonExisting' on type 'QueryRoot'", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 5 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "nonExisting", 14 | "query { ... }" 15 | ], 16 | "type": "QueryRoot", 17 | "field": "nonExisting", 18 | "code": "gql@5.3.1", 19 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 20 | } 21 | }, 22 | { 23 | "message": "There is no field 'nonExistingInFragment' on type 'QueryRoot'", 24 | "locations": [ 25 | { 26 | "line": 12, 27 | "column": 5 28 | } 29 | ], 30 | "extensions": { 31 | "path": [ 32 | "nonExistingInFragment", 33 | "fragment SelfData on QueryRoot { ... }" 34 | ], 35 | "type": "QueryRoot", 36 | "field": "nonExistingInFragment", 37 | "code": "gql@5.3.1", 38 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 39 | } 40 | }, 41 | { 42 | "message": "There is no field 'nonExistingInInlineFragment' on type 'QueryRoot'", 43 | "locations": [ 44 | { 45 | "line": 6, 46 | "column": 13 47 | } 48 | ], 49 | "extensions": { 50 | "path": [ 51 | "nonExistingInInlineFragment", 52 | "...on QueryRoot { ... }", 53 | "self { ... }", 54 | "query { ... }" 55 | ], 56 | "type": "QueryRoot", 57 | "field": "nonExistingInInlineFragment", 58 | "code": "gql@5.3.1", 59 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 60 | } 61 | } 62 | ], 63 | "data": { 64 | "nonExisting": null, 65 | "self": { 66 | "nonExistingInFragment": null, 67 | "nonExistingInInlineFragment": null 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-fragment-spread-type.gql: -------------------------------------------------------------------------------- 1 | query { 2 | self { 3 | ...QueryRoot1stLevel 4 | } 5 | } 6 | 7 | fragment QueryRoot1stLevel on QueryRoot { 8 | id 9 | ...QueryRoot2ndLevel 10 | } 11 | 12 | fragment QueryRoot2ndLevel on QueryRoot { 13 | self { 14 | id 15 | } 16 | ...QueryRoot3rdLevel 17 | } 18 | 19 | fragment QueryRoot3rdLevel on QueryRoot { 20 | again: id 21 | ...NonExistingTypeData 22 | } 23 | 24 | fragment NonExistingTypeData on NonExistingType { 25 | anyField 26 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-fragment-spread-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Fragment spread type 'NonExistingType' is not defined in the schema", 5 | "locations": [ 6 | { 7 | "line": 24, 8 | "column": 10 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "fragment NonExistingTypeData on NonExistingType { ... }" 14 | ], 15 | "code": "gql@5.5.1.2", 16 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Fragment-Spread-Type-Existence" 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-inline-fragment-spread-type.gql: -------------------------------------------------------------------------------- 1 | { 2 | self { 3 | ...on QueryRoot { 4 | id 5 | ...on QueryRoot { 6 | self { 7 | id 8 | } 9 | ...on QueryRoot { 10 | again: id 11 | ...on NonExistingType { 12 | anyField 13 | } 14 | } 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-inline-fragment-spread-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "Fragment spread type 'NonExistingType' is not defined in the schema", 5 | "locations": [ 6 | { 7 | "line": 11, 8 | "column": 27 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "...on NonExistingType { ... }", 14 | "...on QueryRoot { ... }", 15 | "...on QueryRoot { ... }", 16 | "...on QueryRoot { ... }", 17 | "self { ... }", 18 | "query { ... }" 19 | ], 20 | "code": "gql@5.5.1.2", 21 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Fragment-Spread-Type-Existence" 22 | } 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-multiple-fields.gql: -------------------------------------------------------------------------------- 1 | query { 2 | firstNonExisting 3 | secondNonExisting 4 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-multiple-fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "There is no field 'firstNonExisting' on type 'QueryRoot'", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 3 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "firstNonExisting", 14 | "query { ... }" 15 | ], 16 | "type": "QueryRoot", 17 | "field": "firstNonExisting", 18 | "code": "gql@5.3.1", 19 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 20 | } 21 | }, 22 | { 23 | "message": "There is no field 'secondNonExisting' on type 'QueryRoot'", 24 | "locations": [ 25 | { 26 | "line": 3, 27 | "column": 3 28 | } 29 | ], 30 | "extensions": { 31 | "path": [ 32 | "secondNonExisting", 33 | "query { ... }" 34 | ], 35 | "type": "QueryRoot", 36 | "field": "secondNonExisting", 37 | "code": "gql@5.3.1", 38 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 39 | } 40 | } 41 | ], 42 | "data": { 43 | "firstNonExisting": null, 44 | "secondNonExisting": null 45 | } 46 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-mutation.gql: -------------------------------------------------------------------------------- 1 | mutation { 2 | nonExisting 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/error/non-existing-mutation.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "message": "There is no field 'nonExisting' on type 'MutationRoot'", 5 | "locations": [ 6 | { 7 | "line": 2, 8 | "column": 3 9 | } 10 | ], 11 | "extensions": { 12 | "path": [ 13 | "nonExisting", 14 | "mutation { ... }" 15 | ], 16 | "type": "MutationRoot", 17 | "field": "nonExisting", 18 | "code": "gql@5.3.1", 19 | "specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Field-Selections" 20 | } 21 | } 22 | ], 23 | "data": { 24 | "nonExisting": null 25 | } 26 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/aliased-nested-self.gql: -------------------------------------------------------------------------------- 1 | query { 2 | self { 3 | first: self { 4 | id 5 | } 6 | second: self { 7 | id 8 | } 9 | third: self { 10 | id 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/aliased-nested-self.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "self": { 4 | "first": { 5 | "id": "root" 6 | }, 7 | "second": { 8 | "id": "root" 9 | }, 10 | "third": { 11 | "id": "root" 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-arg-allowed-type-mismatch.gql: -------------------------------------------------------------------------------- 1 | query { 2 | # The input expects a Boolean, passing a String/Int/Float can be successfully coerced 3 | withTrueBoolean: id @skip(if: "true") 4 | withTrueInt: id @skip(if: 1) 5 | withTrueFloat: id @skip(if: 1.0) 6 | withFalseBoolean: id @skip(if: "false") 7 | withFalseInt: id @skip(if: 0) 8 | withFalseFloat: id @skip(if: 0.0) 9 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-arg-allowed-type-mismatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "withFalseBoolean": "root", 4 | "withFalseInt": "root", 5 | "withFalseFloat": "root" 6 | } 7 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-in-fragment.gql: -------------------------------------------------------------------------------- 1 | query SomeQuery($include: Boolean!) { 2 | self { 3 | ...SelfData 4 | } 5 | } 6 | 7 | fragment SelfData on QueryRoot { 8 | id 9 | includedSelf: self @include(if: $include) { 10 | id 11 | } 12 | skippedSelf: self @skip(if: $include) { 13 | id 14 | } 15 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-in-fragment.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "self": { 4 | "id": "root", 5 | "includedSelf": { 6 | "id": "root" 7 | } 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-in-fragment.var.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": true 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-in-inline-fragment.gql: -------------------------------------------------------------------------------- 1 | query SomeQuery($include: Boolean!) { 2 | self { 3 | ...on QueryRoot { 4 | id 5 | includedSelf: self @include(if: $include) { 6 | id 7 | } 8 | skippedSelf: self @skip(if: $include) { 9 | id 10 | } 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-in-inline-fragment.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "self": { 4 | "id": "root", 5 | "skippedSelf": { 6 | "id": "root" 7 | } 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/directive-in-inline-fragment.var.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": false 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/enum.gql: -------------------------------------------------------------------------------- 1 | query { 2 | __schema { 3 | withoutQuotes: directives(ofKinds: [QUERY]) { 4 | name 5 | } 6 | withQuotes: directives(ofKinds: ["QUERY"]) { 7 | name 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "__schema": { 4 | "withoutQuotes": [ 5 | { 6 | "name": "include" 7 | }, 8 | { 9 | "name": "skip" 10 | } 11 | ], 12 | "withQuotes": [ 13 | { 14 | "name": "include" 15 | }, 16 | { 17 | "name": "skip" 18 | } 19 | ] 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/field-arg-allowed-type-mismatch.gql: -------------------------------------------------------------------------------- 1 | query { 2 | # The input expects a String, but passing a Boolean/Int/Float gets coerced successfully 3 | passingBoolean: _implements(interface: false) 4 | passingInt: _implements(interface: 15) 5 | passingFloat: _implements(interface: 15.5) 6 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/field-arg-allowed-type-mismatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "passingBoolean": false, 4 | "passingInt": false, 5 | "passingFloat": false 6 | } 7 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/id.gql: -------------------------------------------------------------------------------- 1 | query { 2 | id 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/id.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "root" 4 | } 5 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/include-and-variables.gql: -------------------------------------------------------------------------------- 1 | query SomeQuery($include: Boolean!) { 2 | id 3 | self @include(if: $include) { 4 | id 5 | } 6 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/include-and-variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "root", 4 | "self": { 5 | "id": "root" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/include-and-variables.var.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": true 3 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/introspection-extensions.gql: -------------------------------------------------------------------------------- 1 | query ExtensionsIntrospectionQuery { 2 | __schema { 3 | extensions { 4 | isNamespaced 5 | } 6 | types { 7 | name 8 | extensions { 9 | elementName 10 | namespacedName 11 | possibleValues 12 | isOneOf 13 | } 14 | fields { 15 | name 16 | extensions { 17 | isMutation 18 | isSensitiveDataElement 19 | } 20 | args { 21 | name 22 | extensions { 23 | isSensitiveDataElement 24 | } 25 | } 26 | } 27 | inputFields { 28 | name 29 | extensions { 30 | isSensitiveDataElement 31 | } 32 | } 33 | enumValues { 34 | name 35 | extensions { 36 | isSensitiveDataElement 37 | } 38 | } 39 | } 40 | directives { 41 | name 42 | extensions { 43 | needsDataToExecute 44 | fieldDirectiveSupportedTypeNamesOrDescriptions 45 | } 46 | args { 47 | name 48 | extensions { 49 | isSensitiveDataElement 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/introspection-query.gql: -------------------------------------------------------------------------------- 1 | query IntrospectionQuery { 2 | __schema { 3 | queryType { 4 | name 5 | } 6 | mutationType { 7 | name 8 | } 9 | subscriptionType { 10 | name 11 | } 12 | types { 13 | ...FullType 14 | } 15 | directives { 16 | name 17 | description 18 | locations 19 | args { 20 | ...InputValue 21 | } 22 | } 23 | } 24 | } 25 | 26 | fragment FullType on __Type { 27 | kind 28 | name 29 | description 30 | fields(includeDeprecated: true) { 31 | name 32 | description 33 | args { 34 | ...InputValue 35 | } 36 | type { 37 | ...TypeRef 38 | } 39 | isDeprecated 40 | deprecationReason 41 | } 42 | inputFields { 43 | ...InputValue 44 | } 45 | interfaces { 46 | ...TypeRef 47 | } 48 | enumValues(includeDeprecated: true) { 49 | name 50 | description 51 | isDeprecated 52 | deprecationReason 53 | } 54 | possibleTypes { 55 | ...TypeRef 56 | } 57 | } 58 | 59 | fragment InputValue on __InputValue { 60 | name 61 | description 62 | type { 63 | ...TypeRef 64 | } 65 | defaultValue 66 | } 67 | 68 | fragment TypeRef on __Type { 69 | kind 70 | name 71 | ofType { 72 | kind 73 | name 74 | ofType { 75 | kind 76 | name 77 | ofType { 78 | kind 79 | name 80 | ofType { 81 | kind 82 | name 83 | ofType { 84 | kind 85 | name 86 | ofType { 87 | kind 88 | name 89 | ofType { 90 | kind 91 | name 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/nested-fragments.gql: -------------------------------------------------------------------------------- 1 | query { 2 | self { 3 | ...QueryRoot1stLevel 4 | } 5 | } 6 | 7 | fragment QueryRoot1stLevel on QueryRoot { 8 | id 9 | ...QueryRoot2ndLevel 10 | } 11 | 12 | fragment QueryRoot2ndLevel on QueryRoot { 13 | self { 14 | id 15 | } 16 | ...QueryRoot3rdLevel 17 | } 18 | 19 | fragment QueryRoot3rdLevel on QueryRoot { 20 | again: id 21 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/nested-fragments.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "self": { 4 | "id": "root", 5 | "self": { 6 | "id": "root" 7 | }, 8 | "again": "root" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/nested-inline-fragments.gql: -------------------------------------------------------------------------------- 1 | { 2 | self { 3 | ...on QueryRoot { 4 | id 5 | ...on QueryRoot { 6 | self { 7 | id 8 | } 9 | ...on QueryRoot { 10 | again: id 11 | } 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/Unit/fixture/success/nested-inline-fragments.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "self": { 4 | "id": "root", 5 | "self": { 6 | "id": "root" 7 | }, 8 | "again": "root" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/nested-self.gql: -------------------------------------------------------------------------------- 1 | query { 2 | self { 3 | self { 4 | id 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/nested-self.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "self": { 4 | "self": { 5 | "id": "root" 6 | } 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/self.gql: -------------------------------------------------------------------------------- 1 | query { 2 | self { 3 | id 4 | } 5 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/self.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "self": { 4 | "id": "root" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-connection.gql: -------------------------------------------------------------------------------- 1 | { 2 | id 3 | self @skip(if: true) { 4 | id 5 | } 6 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-connection.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "root" 4 | } 5 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-field.gql: -------------------------------------------------------------------------------- 1 | { 2 | id 3 | again: id @skip(if: true) 4 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-field.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "root" 4 | } 5 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-not-connection.gql: -------------------------------------------------------------------------------- 1 | { 2 | id 3 | self @skip(if: false) { 4 | id 5 | } 6 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-not-connection.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "root", 4 | "self": { 5 | "id": "root" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-not-field.gql: -------------------------------------------------------------------------------- 1 | { 2 | id 3 | again: id @skip(if: false) 4 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/skip-not-field.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "root", 4 | "again": "root" 5 | } 6 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/variable-inside-array.gql: -------------------------------------------------------------------------------- 1 | query GetDirectivesOfKind($kind: String!) { 2 | __schema { 3 | directives( 4 | ofKinds: [$kind] 5 | ) { 6 | name 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/Unit/fixture/success/variable-inside-array.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "__schema": { 4 | "directives": [ 5 | { 6 | "name": "include" 7 | }, 8 | { 9 | "name": "skip" 10 | } 11 | ] 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /tests/Unit/fixture/success/variable-inside-array.var.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "query" 3 | } --------------------------------------------------------------------------------