Code Monkey home page Code Monkey logo

graphql's People

Contributors

armetiz avatar bartfeenstra avatar bgfist avatar big-shark avatar danez avatar dezzak avatar fritz-gerneth avatar fubhy avatar gitter-badger avatar herlevsen avatar jalle19 avatar keichinger avatar lslinnet avatar m-naw avatar mathroc avatar mrbarletta avatar oligus avatar philsturgeon avatar pmelab avatar portey avatar powerkiki avatar roippi avatar scottjoplin avatar seb2411 avatar stefanorg avatar symm avatar theghoul21 avatar viniychuk avatar xuxucode avatar zombaya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql's Issues

Unexpected input field value causes `TypeError`

Hi. I have this code in the userEdit field:

/**
 * @inheritdoc
 */
public function getName()
{
    return 'userEdit';
}
/**
 * @inheritdoc
 */
public function getType()
{
    return new UserType();
}
/**
 * @inheritdoc
 */
public function build(FieldConfig $config)
{
    $this->addArgument(
        new InputField([
            'name' => 'id',
            'type' => new NonNullType(new IntType()),
        ])
    )->addArgument(
        new InputField([
            'name' => 'data',
            'type' => new NonNullType(new InputObjectType([
                'name' => 'data',
                'fields' => [
                    [
                        'name' => 'fullName',
                        'type' => new NonNullType(new StringType()),
                    ],
                ],
            ])),
        ])
    );
    parent::build($config);
}

and the command:

mutation m {
  userEdit(id: 1000000, data: 0) {
    fullName
  }
}

returns:

{
  "errors": {
    "message": "Type error: Argument 1 passed to Youshido\\GraphQL\\Validator\\ResolveValidator\\ResolveValidator::processInputObject() must be an instance of Youshido\\GraphQL\\Parser\\Ast\\ArgumentValue\\InputObject, instance of Youshido\\GraphQL\\Parser\\Ast\\ArgumentValue\\Literal given, called in /var/www/symfony/vendor/youshido/graphql/src/Validator/ResolveValidator/ResolveValidator.php on line 101"
  }
}

Any unexpected value ([], 0, "str") for the data argument is not validated and causes to TypeError.

Also this request for the same schema:

mutation m {
  userEdit(id: 1000000, data: {unknownField: "a"}) {
    fullName
  }
}

returns only [] without any errors/exceptions.

Extending AbstractField does not work for mutation fields

Hi @viniychuk,

Maybe, I am doing something wrong, but when I try define mutations in such a way:

private function getRootMutation() {
        return new ObjectType([
            'name' => 'RootMutation',
            'fields' => [
                // here's our likePost mutation
                'likePost' => new LikePost()
            ]
        ]);
    }

and then define LikePost in the following way:

class LikePost extends AbstractField
{

    public function build(FieldConfig $config) {

        $config->addArgument('id', new NonNullType(new IntType()));
    }

    public function getType()
    {
        return new IntType();
    }

    public function resolve($value, array $args, ResolveInfo $info)
    {
        return 2;
    }
}

then it does not work. I receive error that likePost field is undefined.
I tried also extending AbstractInputField, however InputFieldConfig does not contain addArgument function.

Is it possible to do in the current version?

resolve function on ObjecType not allowed?

Here's my example which the runtime throws the exception:

Call to undefined method Youshido\GraphQL\Type\Object\ObjectType::resolve()

        $productType = new ObjectType([
            'name' => 'ProductType',
            'fields' => [
                'sId' => new IntType(),
                'title' => new StringType(),
                'comments' => new StringType(),
                'price' => new FloatType(),
                'priceStr' => new StringType(),
                'finalPrice' => new FloatType(),
                'finalPriceStr' => new StringType(),
                'currency' => new StringType(),
                'Link' => new StringType(),
                'link' => new StringType(),
            ],
            'resolve' => function()     <------- is this allowed?
            {
                return [
                    'sId' => 100,
                    'title' => 'Starwar film',
                    'comments' => 'no comment',
                    'price' => 13.5,
                    'priceStr' => '$13.5',
                    'finalPrice' => 10.5,
                    'finalPriceStr' => '$10.5',
                    'currency' => 'USD',
                    'Link' => 'http://google.com',
                    'link' => 'http://google.com'
                ];
            }
        ]);

I was following the first example in this section of readMe:
https://github.com/Youshido/GraphQL#objects

when we can not resolve field, it passes null as $contextValue for resolve function

Hi

class PostType extends \Youshido\GraphQL\Type\Object\AbstractObjectType
{

    /**
     * @param \Youshido\GraphQL\Config\Object\ObjectTypeConfig|TypeConfigInterface $config
     * @return mixed
     */
    public function build($config)
    {
        $config->addField('id', [
            'type' => new IdType(),
            'resolve' => function ($value, $args){
                return $value['post_id'];
            },
        ]);

in my db, the id field is named post_id, i want to resolve post_id to id
but in resolve function, $value is always null

it seems you have issue in https://github.com/Youshido/GraphQL/blob/master/src/Execution/Processor.php#L274

because

        if (!$resolved && $field->getType()->getNamedType()->getKind() == TypeMap::KIND_SCALAR) {
            $resolved = true;
        }
        if ($resolveFunction = $field->getConfig()->getResolveFunction()) {
           .....
            } else {
                $resolverValue = $resolveFunction($resolved ? $resolverValue : $contextValue, $fieldAst->getKeyValueArguments(), $resolveInfo);
            }
        }

when $resolved = true and $resolverValue = null, $resolveFunction will have null $contextValue

Fragment reference "fReservation" not found on model "CourtReservation"

Full query:

query {
    user {
        ...fUser
        reservations {
            ...fReservation
        }
    }
}
fragment fReservation on Reservation {
    id
    ... on CourtReservation {
        players {
            id
            user {
                ...fUser
            }
        }
    }
    ... on ClassReservation {
        user {
            ...fUser
        }
    }
}
fragment fUser on User {
    id
    fullname
}

When I debug ResolveValidator::assertValidFragmentForField(), $fragment->getModel() seems to be "User".

Where does User come from..? The fragment is only applied to reservations, which is a new ListType(new ReservationInterface()). Is it confused by fUser?

When I try another server library, the query works. Which is wrong? The query seems correct...

Mutation helper class - how to

Hi,

I have a Yii project that i have implemented with Youshido/GraphQL and it works great!

Based on Yiis classes i can autogenerate code for querys and now im looking on mutation.

Smal repo: https://github.com/Vendium/Youshido-GraphQL-Yii

In your documentation you have written that "You can create a mutation by extending AbstractObjectType", my question is how to do this so you dont get a big Schema file. For query its made easy by working with types that have relations with each other.

So dose any one have a small code exampel of how to work with mutations without geting a big schema file and what i assume is to place mutations in type files.

thanks!

Root query and mutation don't have __typename

Query:

mutation { // or query or empty
  __typename
}

Response:

{
  "errors": [
    {
      "message": "Field \"__typename\" not found in type \"Mutation\"",
      "locations": [
        {
          "line": 20,
          "column": 3
        }
      ]
    }
  ]
}

BTW: Big thanks for locations key ๐Ÿ‘

Error locations

I was testing this library last week and noticed that you do not support the error locations that are part of the GraphQL spec.

Is there a way to enable this or is this in the works?

Query with missing fragment does not throw exception

if fragment does not exist, PHP Fatal error: Call to a member function getModel() on null.

query {
  posts {
    ...post
  }
}

I believe throwing of exception with something like Unknown fragment "post". will be more usefull

Resolve only the requested fields

Is there a recommended way only to resolve the fields that the consumer has requested? In our model we have a few run-time calculated fields, ideally these aren't resolved on every request if the consumer does not actually ask for them.

Poking around the code I can't see a way to find the actual fields requested in the field resolver. I can see the entire query but as a field can be exposed from multiple nodes in the graph it's hard to infer the context it is being resolved for.

Thanks

NonNullType inside a List of InputObjects are able to be null

As the title says, if you define a field inside an inputobject that is in a list to be NonNullable, the validator does not catch it if the variable is not set.

I've attached my test-classes: TestMutation.zip.

The query I tried to run:

mutation{
  Test(test:{
    a:[
    ],
    b:[
      {
        c:"aaaa"
      },
      {

      }
    ],
  }) {
    name
  }
}

The rules for TestInput:

$config -> addField('a' , ['type' => new ListType(new IntType())        , 'description' => 'a'])
        -> addField('b' , ['type' => new ListType(new InputObjectType([
                                       'name'    => 'test_b',
                                       'fields'  => [
                                         'c'           =>  new NonNullType(new StringType()),
                                         ]
                                         ]))
                                      ])
        -> addField('d' , ['type' => new InputObjectType([
                                       'name'    => 'test_d',
                                       'fields'  => [
                                         'c'           =>  new NonNullType(new StringType()),
                                         ]
                                         ])
                                      ])

The validator does catch it if the field c of d is not set.

AbstractInputObjectType: Unknown argument 'id' on field 'createPart' when performing a mutation

Hi!

Thanks for the hard work you have put into this project!

I have a mutation field:

class CreatePartField extends AbstractField
{
  public function getType()
  {
      return new PartInputType();
  }

  public function build(FieldConfig $config)
  {
      $config->addArguments(new PartInputType());
  }

  public function resolve($value, array $args, ResolveInfo $info)
  {
     // return something...
  }
}

And the type:

class PartInputType extends AbstractInputObjectType
{
    public function build($config)
    {
        $config
            ->addField('id', new IntType())
            ->addField('name', new NonNullType(new StringType()))
            ->addField('description', new NonNullType(new StringType()))
            ->addField('notes', new StringType())
            ->addField('minimumStock', new IntType());
    }
}

I've add the field to the mutation fields:

class GraphQLSchema extends AbstractSchema
{
    public function build(SchemaConfig $config)
    {
        $config->getQuery()->addFields([
            new RetrievePartField(),
            new AllPartsField(),
        ]);

          $config->getMutation()->addFields([
          new CreatePartField()
        ]);
    }

}

I send the mutation request:

mutation { createPart( id: 3, name: "Another test",  description: "Another  description", minimumStock: "12", notes: "Another note")  }

I keep getting the error: Unknown argument "id" on field "createPart"

The field doesn't seem to like accepting AbstractInputObjectType as an argument (maybe?)

I've looked into all of the docs and examples, but I have not yet found a solution...

Perhaps I'm formatting the mutation request wrong...

Any help would be greatly appreciated! Thank you!

Definition of args in object oriented approach.

GraphQL Fields can have arguments. It is easy to do in inline-approach, however, I cannot achieve it in object oriented approach. I need it badly. I edited this function in the following way:

public function getRules()
    {
        return [
            'name'        => ['type' => TypeService::TYPE_STRING, 'required' => true],
            'description' => ['type' => TypeService::TYPE_STRING],
            'fields'      => ['type' => TypeService::TYPE_ARRAY_OF_FIELDS_CONFIG, 'final' => true],
            'interfaces'  => ['type' => TypeService::TYPE_ARRAY_OF_INTERFACES],
            'args'     => ['type' => TypeService::TYPE_ARRAY_OF_INPUT_FIELDS]
        ];
    }

However, still $args are empty in the resolve function. Do you know how to do that easily? I will be grateful for any help.

Non-null argument for input object of mutation fails validation

I have a mutation, defined as such:

<?php
namespace AppBundle\GraphQL\Mutation;

use AppBundle\GraphQL\Type\TestMutationInputType;
use Youshido\GraphQL\Config\Field\FieldConfig;
use Youshido\GraphQL\Execution\ResolveInfo;
use Youshido\GraphQL\Type\NonNullType;
use Youshido\GraphQL\Type\Scalar\IntType;
use Youshido\GraphQLBundle\Field\AbstractContainerAwareField;

class TestMutationField extends AbstractContainerAwareField
{

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return new IntType();
    }

    /**
     * {@inheritdoc}
     */
    public function build(FieldConfig $config)
    {
        $config->addArgument('input', new NonNullType(new TestMutationInputType()));
    }

    /**
     * {@inheritdoc}
     */
    public function resolve($value, array $args, ResolveInfo $info)
    {
        return 0;
    }
}

The input type is defined as such:

<?php
namespace AppBundle\GraphQL\Input;

use Youshido\GraphQL\Type\InputObject\AbstractInputObjectType;
use Youshido\GraphQL\Type\ListType\ListType;
use Youshido\GraphQL\Type\NonNullType;
use Youshido\GraphQL\Type\Scalar\StringType;

class TestMutationInputType extends AbstractInputObjectType
{

    /**
     * {@inheritdoc}
     */
    public function build($config)
    {
        $config->addFields([
            'nullField' => new StringType(),
            'nonNullField' => new NonNullType(new StringType()),
        ]);
    }
}

Executing this mutation and providing values for all the fields on the input type fails with the following message:

{
  "data": {
    "testMutation": null
  },
  "errors": [
    {
      "message": "Not valid type for argument \"input\" in query \"testMutation\""
    }
  ]
}

If I then remove the NonNullType from nonNullField the mutation executes correctly. I've poked through the code but nothing obvious stood out to me.

Regards

Confusing of the naming

I think the name Field used for GraphQL(Youshido) is different from Field in GraphQL documentation.

Field in GraphQL(Youshido) refers to an instance of a type(object) (including the resolve method).
Field in GraphQL(doc) refers to property of a object.

If my understanding is correct. Shall we use another name for Field for Youshido?

Syntax error in graphql not throws error

tried on last version

schema:

type Query {
  user: User
} 
type User {
  key: Int
}

query:

{
  user {
    key { // empty selection, causing invalid query

    }
  }
}

If i user graphql-js:

{
  "errors": [
    {
      "message": "Syntax Error GraphQL request (5:5) Expected Name, found }\n\n4:       \n5:     }\n       ^\n6:   }\n",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ]
    }
  ]
}

With this package:

{
  "data": {
    "user": {
      "key": null
    }
  }
}

There is no error thrown and also invalid data, key data should be available only if execution of query started, not in part of validating schema

Fragments do not appear to work

{
            oneComparison: Post(id: 1) {
                title
            }
            twoComparison: Post(id: 1) {
                ...Fields
            }
        }
        
        fragment Fields on Post {
            title
        }

Returns this:

{"data":{"oneComparison":{"title":"string"},"twoComparison":[]}}

How to manage a List of Posts

In the examples ListType is used with interfaces
But what if I want a list of posts? How do you handle that?

Tried as ListType ( new PostType()) and returned an array of posts and it didn't work.

Thanks!

PS: Thanks for the awesome work ! tried many tools and this one was the best php helper/library I found, very well documented. I just made a PR to the awesome list for PHP related projects:
chentsulin/awesome-graphql#71 #71

Requesting undefined subfield results in a fatal error

If you request a subfield which is not defined, you get a fatal error.

Example-query

{Test{
  name,
  bla {
  }
}}

The test-type only has the field name defined. The subfield bla is never defined which causes the fatal error.

Testfiles

testfiles.zip

Stacktrace

( ! ) Fatal error: Uncaught TypeError: Argument 2 passed to Youshido\GraphQL\Execution\Processor::processQueryAST() must be an instance of Youshido\GraphQL\Field\AbstractField, null given, called in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 332 and defined in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 127
( ! ) TypeError: Argument 2 passed to Youshido\GraphQL\Execution\Processor::processQueryAST() must be an instance of Youshido\GraphQL\Field\AbstractField, null given, called in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 332 in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 127
Call Stack
#TimeMemoryFunctionLocation
10.0002384928{main}( ).../graphql.php:0
20.0089706880Sigura\Mods\Industries\Graphql->__construct( ).../graphql.php:8
30.12322184024Youshido\GraphQL\Execution\Processor->processPayload( ).../Graphql.class.php:122
40.12482253088Youshido\GraphQL\Execution\Processor->executeOperation( ).../Processor.php:76
50.12492270560Youshido\GraphQL\Execution\Processor->processQueryAST( ).../Processor.php:118
60.12512395400Youshido\GraphQL\Execution\Processor->collectValueForQueryWithType( ).../Processor.php:135
70.12522398864Youshido\GraphQL\Execution\Processor->processQueryFields( ).../Processor.php:171
80.12542424840Youshido\GraphQL\Execution\Processor->processQueryAST( ).../Processor.php:332

Optional argument throws if missing in query

schema:

type Query {
  getSomething(sort:SortType): String //sort not required
}

query:

query SomeQuery($sort:SortType) {
  getSomething(sort: $sort)
}

variables:
NONE or

{}

response

{
  "errors": [
    {
      "message": "Variable \"sort\" does not exist for query \"getSomething\""
    }
  ]
}

Invalid sub-selection of field

tried on last version

schema:

type Query {
  user: User
} 
type User {
  key: Int
}

query:

{
  user {
    key { 
      someKey // trying to sub-select on Int
    }
  }
}

If i user graphql-js:

{
  "errors": [
    {
      "message": "Field \"key\" of type \"Int\" must not have a sub selection.",
      "locations": [
        {
          "line": 3,
          "column": 9
        }
      ]
    }
  ]
}

With this package:

{
  "data": {
    "user": {
      "key": null
    }
  }
}

There is no error thrown and also invalid data, key data should be available only if execution of query started, not in part of validating schema

NonNullType not casting to string in query

I'm using NonNullType in my return type like this:

class PersonType extends AbstractObjectType
{
    /**
     * @param ObjectTypeConfig $config
     *
     * @return mixed
     */
    public function build($config)
    {
        $config->addFields([
            'id' => new NonNullType(new IdType()),
            'firstName' => new NonNullType(new StringType()),
            'lastName' => new NonNullType(new StringType()),
        ]);
    }
}

The IDs of my persons are UUIDs. With the code like this, the result is:

{
    "data": {
        "persons": [
            {
                "id": {},
                "firstName": "Bernhard",
                "lastName": "Schussek"
            }
        ]
    }
}

As you can see, the UUID is not cast to a string, but converted to {}. However if I remove the NonNullType around IdType, the result is as expected:

{
    "data": {
        "persons": [
            {
                "id": "6cfb044c-9c0a-4ddd-9ef8-a0b940818db3",
                "firstName": "Bernhard",
                "lastName": "Schussek"
            }
        ]
    }
}

Resolve cannot be a field of ObjectType - mistake in description

Thank you for good documentation, however. there is a problem with description of inline-approach:

<?php
use Youshido\GraphQL\Type\Object\ObjectType;
use Youshido\GraphQL\Type\Scalar\StringType;

// creating a root query structure
$rootQueryType = new ObjectType([
    // name for the root query type doesn't matter, by the convention it's RootQueryType
    'name'   => 'RootQueryType',
    'fields' => [
        'latestPost' => new ObjectType([ // the Post type will be extended from the generic ObjectType
            'name'    => 'Post', // name of our type โ€“ "Post"
            'fields'  => [
                'title'   => new StringType(),  // defining the "title" field, type - String
                'summary' => new StringType(),  // defining the "summary" field, also a String type
            ],
            'resolve' => function () {          // this is a resolve function
                return [                        // for now it returns a static array with data
                    "title"   => "New approach in API has been revealed",
                    "summary" => "This post describes a new approach to create and maintain APIs",
                ];
            }
        ])
    ]
]);

Resolve function cannot be there. It is not valid.

Valid query not possible to execute

This query combining unions and fragments does not work:

{
  user(id: 2) {
    ...user
  }
}

fragment user on UserUnion {
  ... on User {
    id
  }
}

schema contains query user which can return UserUnion which will be resolved to type User with field id. Exception thrown: Fragment reference "user" not found on model "User"

Bug: invalid output type returned without error if NonNull type used

If !Int is resolved to null, there's no error or exception thrown

$config->addField('id', [
  'type' => new NonNullType(new IntType()),
  'resolve' => function() { return null; }
]);

graphql-js is notificating about this behavior with

{
      "message": "Cannot return null for non-nullable field User.id.",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ]
    }

in response errors key. Same is returned if resolver returns string not coercible to int.

variables in nested fields and queries don't work

This works fine:

{ foo { bar(value:"baz") } }

But the following equivalent query with provided variables {value:"baz"} bombs out:

query nestedQuery($value:String!){
  foo {
    bar(value:$value)
}

Error message is somewhat opaque: "Value not set to variable else"

I've provided a regression test here: roippi@54f310b

The fix is non-trivial so I don't know if/when I'll have a pull request available. I've traced through it and it looks like $this->resolveValidator->validateArguments is only getting invoked at the operation level, not at the individual field level.

Thanks for the awesome library.

thoughts on implementing Query Complexity Analysis?

This is a feature that's popping up in a few other framework implementations, and I think it's pretty killer - it lets you do a reasonable job at statically detecting pathologic queries.

There are some more complex ideas floating out there in the community, namely graphql/graphql-js#304. This could be used both for complexity/cost analysis in addition to query resolution optimization, though it seems more useful for optimization. Probably overkill here.

Has anyone already thought of implementing this here, or should I take a crack at it?

How to create a Mutation with a List of (something) as argument

Lets say I have a mutation like this

mutation
{createPost(
  title: 'Copa America', 
  description: ' Latest results ',
  authors: [  
     {name: 'Maradona', email: '[email protected]' } ,
     {name: 'Messi', email: '[email protected]' } ]  
)}

How Do I handle this scenario? -

I tried the author ListType( new AuthorType()) ?

ListType is not iterating each AuthorType sent on the request so its failing with Not valid Type....

ResolveValidator line

if (!$argumentType->isValidValue($argumentType->parseValue($argument->getValue()->getValue()))) {

Is receiving the entire array sent and not a single iteration..

I guess we need a InputListType ? or I am missing something

Support fragments on Unions and Interfaces

@fubhy's comments in gitter:

Fragments currently don't work with interfaces or union types... only normal types or composite types.

E.g. this doesn't work:

query {
  somethingThatReturnsAUnion(foo: "bar") {
     ... on Something { // Something is a valid type for this union!
        id
     }
  }
}

That is, because we currently only load the inner type (resolve any compose types) and then compare the name of that type with the name of the fragment. In case of unions/interfaces however, we need to also compare it with any of the possible types of the interface/union.
And even possible further nested types.

Will add failing test case.

Is it possible to extend Types?

Is there a possibility of extending types?
For example, if I have PostType and I want to create the next type called SpecialPostType (which has all fields that PostType has, but also a few additional), can I extend it somehow?

I do not want to use Interfaces, because as far as I understand, Interfaces will make me to define resolve functions for PostType and SpecialPostType separately.

Problem with enum

Hi,

Using a "-" in the name of an enum causes this error:

{
  "errors": [
    {
      "message": "Config is not valid for TestType\nField \"values\" expected to be \"type\" but got \"array\""
    }
  ]
}

Code:

use \Youshido\GraphQL\Type\Object\AbstractObjectType;
use \Youshido\GraphQL\Type\Scalar\IdType;
use \Youshido\GraphQL\Type\Scalar\StringType;
use \Youshido\GraphQL\Type\Scalar\DateType;
use \Youshido\GraphQL\Type\Scalar\BooleanType;
use \Youshido\GraphQL\Type\ListType\ListType;
use \Youshido\GraphQL\Type\Enum\AbstractEnumType;

class TestType extends AbstractEnumType
{
    public function getValues()
    {
        $result = array();
        $result[]= array(
                'value' => 1,
                'name' => "aaa-", 
            );
        $result[]= array(
                'value' => 2,
                'name' => "bbb", 
        );
        return $result;
    }


}

It is possible to execute invalid query

Query like this:

{
  user(id: 11457349) {

  } 
}

is invalid, but it is possible to execute it with package. It will resolve to all user keys, but I don't believe this is valid either. Can you confirm this? Or am I mistaken?

Bug: optional variable does not exist on query

Query:

query userById($offset:Int) {
  user(id: 2) {
    id
    photoAlbums(offset: $offset) {
      edges {
        id
      }
    }
  }
}

Response:

{
  "data": {
    "user": {
      "id": 2,
      "photoAlbums": null
    }
  },
  "errors": [
    {
      "message": "Variable \"offset\" does not exist for query \"photoAlbums\""
    }
  ]
}

If i dont use named query

{
  user(id: 2) {
    id
    photoAlbums {
      edges {
        id
      }
    }
  }
}

response is

{
  "data": {
    "user": {
      "id": 2,
      "photoAlbums": {
        "edges": [
          {
            "id": 10000965
          },
          ....
        ]
      }
    }
  }
}

Minor documentation issue?

Hi,

First up - awesome work, I just started looking into this project after working with GraphQL-php for some time. I really like the OOP type declaration approach.

I come across an issue in the getting started document, which I think might just be outdated documentation?

public function build(TypeConfigInterface $config)
{
    $config
        ->addField('title', new NonNullType(new StringType()), [
            'description'       => 'This field contains a post title',
            'isDeprecated'      => true,
            'deprecationReason' => 'field title is now deprecated',
            'args'              => [
                'truncated' => new BooleanType()
            ],
            'resolve'           => function ($value, $args) {
                return (!empty($args['truncated'])) ? explode(' ', $value)[0] . '...' : $value;
            }
        ])
        ->addField('summary', new StringType())
        ->addField('likeCount', new IntType());
    $config->addArgument('id', new IntType());
}

public function resolve($value, $args, $info)
{
    return [
        "title"     => "Title for the latest Post",
        "summary"   => "Post summary",
        "likeCount" => 2
    ];
}
  1. inline documentation says it is ObjectTypeConfig and not TypeConfigInterface.

  2. addFields only takes 2 arguments, how is it configured then?

  3. AbstractObjectType does'nt not contain a resolve() to override, and if I define a resolve function here, it is not called.

DateTimeType clarification

Hi,
using DateTimeType enforce string validation against a date format, i found that the actual implementation of DateTimeType doesn't allow null value as mutation parameter and as scalar value.

As an example if in the todo example app we add a expire field as DateTime we can query

class TodoType extends AbstractObjectType
{
    public function build($config)
    {
        $config->addFields([
            'id' => new NonNullType(new IdType()),
            'title' => new StringType(),
            'completed' => new BooleanType(),
            'expire' => new DateTimeType("d-m-Y")
        ]);
    }

}

if we issue a query

fragment todo on Todo {
  id
  title
  completed
  expire
}

{
  todos {
    ...todo
  }
}

we get

{
  "data": {
    "todos": [
      null
    ]
  },
  "errors": [
    {
      "message": "Not valid resolved type for field \"expire\""
    }
  ]
}

Also in case of mutation

mutation {
   save(id:1, title: "todo mod", expire: null) {
    ...todo
  }
}

the error is

{
  "data": {
    "save": null,
    "toggleAll": [
      null
    ]
  },
  "errors": [
    {
      "message": "Not valid type for argument \"expire\" in query \"save\"",
      "locations": [
        {
          "line": 10,
          "column": 34
        }
      ]
    },
    {
      "message": "Not valid resolved type for field \"expire\""
    }
  ]
}

Non-null field can return null in response

tried on last version

schema:

type Query {
  user: User
} 
type User {
  key: Int!
}

query:

{
  user {
    key 
  }
}

If i user graphql-js:

{
  "data": {
    "user": null
  },
  "errors": [
    {
      "message": "Cannot return null for non-nullable field User.key.",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ]
    }
  ]
}

With this package:

{
  "data": {
    "user": {
      "key": null
    }
  }
}

There is no error thrown

Query where an object has no fields requested, returns internal representation

Hi, we've run in to a situation where if we execute a query such as:

{
  name
  primaryAddress
}

Where primaryAddress is a complex object with it's own type. We receive a response like so:

{
  "name": "Bob",
  "primaryAddress": {

        },
        "__cloner__": {

        },
        "__isInitialized__": false
      }
}

The types are configured like so:

<?php
namespace App\AppBundle\GraphQL;

use Youshido\GraphQL\Type\ListType\ListType;
use Youshido\GraphQL\Type\Object\AbstractObjectType;
use Youshido\GraphQL\Type\Scalar\BooleanType;
use Youshido\GraphQL\Type\Scalar\DateTimeTzType;
use Youshido\GraphQL\Type\Scalar\DateType;
use Youshido\GraphQL\Type\Scalar\FloatType;
use Youshido\GraphQL\Type\Scalar\IdType;
use Youshido\GraphQL\Type\Scalar\IntType;
use Youshido\GraphQL\Type\Scalar\StringType;

class PersonType extends AbstractObjectType {

    /**
     * @param mixed $config
     */
    public function build($config) {
        return $config
        ->addFields(['name' => ['type' => new StringType(), 'description' => 'The name of the person']])
        ->addFields(['primaryAddress' => ['type' => new AddressType(), 'description' => 'Their primary address']])
    }

    /**
     */
    public function getName() {
        return "Person";
    }
}

class AddressType extends AbstractObjectType {

    /**
     * @param mixed $config
     */
    public function build($config) {
        return $config
                      ->addFields(['street' => ['type' => new StringType(), 'description' => 'The street']])
                      ->addFields(['postcode' => ['type' => new StringType(), 'description' => 'The postcode']]);
    }

    /**
     */
    public function getName() {
        return 'Address';
    }
}

We are using doctrine behind the scenes, this seems to be outputting the contents of our proxy object. If we execute the query with an empty field list (e.g. primaryAddress {}) then the query fails with an expected message of "You have to specify fields for primaryAddress". I would expect the same result if you miss off the braces.

Are we misconfiguring our types or is this a bug?

Regards,

if i use TimestampType with value integer, it will return null after being resolved

$config->addField('date', new TimestampType());

In my database, i have field date as unix timestamp (which is integer)

In this class
https://github.com/Youshido/GraphQL/blob/master/src/Type/Scalar/TimestampType.php

public function isValidValue($value)
    {
        if (is_object($value)) {
            return true;
        }
        return is_int($value);
    }

if i pass an integer, it will return true
but when it is being serialized

 public function serialize($value)
    {
        if ($value === null || !is_object($value)) {
            return null;
        }
        return $value->getTimestamp();
    }

the previous valid integer will be serialized into null

Strange issue with list of values

Hi
Query:

mutation {
  upvote(idPhotos:[320131273]) {
    id
  }
}

If i define idPhotos this way

$config->addArgument('idPhotos', new NonNullType(new ListType(new IntType())));

I get error Not valid type for argument "idPhotos" in query "upvote", but if I define it this way

$config->addArgument('idPhotos', new NonNullType(new ListType(new NonNullType(new IntType()))));

everything works as expected.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.