Commit Graph

431 Commits

Author SHA1 Message Date
Daniel Tschinder
fde7df534d Robust type info
There are possibilities for errors during validation if a schema is not valid when provided to TypeInfo. Most checks for validity existed, but some did not. This asks flow to make those checks required and adds the remaining ones. Important now that we allow construction of invalid schema.

ref: graphql/graphql-js#1143
2018-02-15 12:22:29 +01:00
Daniel Tschinder
97e8a9e200 Move schema validation into separate step (type constructors)
This is the second step of moving work from type constructors to the schema validation function.

ref: graphql/graphql-js#1132
2018-02-15 12:14:08 +01:00
Daniel Tschinder
6d08c342c9 Address recent SDL spec changes
This should be the last set of spec changes for a standardized SDL

ref: graphql/graphql-js#1139
2018-02-13 18:18:50 +01:00
Daniel Tschinder
50cbfb4a44 Fix Bug in PossibleFragmentSpreads validator
ref: graphql/graphql-js@7e147a8dd6
2018-02-13 18:08:05 +01:00
Daniel Tschinder
9387548aa1 Better Predicates
Introduces new assertion functions for each kind of type mirroring the existing ones for the higher order types.

ref: graphql/graphql-js#1137
2018-02-13 18:04:03 +01:00
Daniel Tschinder
60df83f47e Preserve original coercion errors, improve error quality.
This is a fairly major refactoring of coerceValue which returns an Either so it can return a complete collection of errors. This allows originalError to be preserved for scalar coercion errors and ensures *all* errors are represented in the response.

This had a minor change to the logic in execute / subscribe to allow for buildExecutionContext to abrupt complete with multiple errors.

ref: graphql/graphql-js#1133
2018-02-13 16:51:44 +01:00
Daniel Tschinder
6d45a22ba4 Always extract extensions from the original error if possible
ref: graphql/graphql-js#2d08496720088dbe65ebea312c8526bd48fb8ee8
2018-02-13 10:42:56 +01:00
Daniel Tschinder
cf276340a4 Fix printError/locations for multiple nodes.
If a GraphQLError represents multiple nodes across files (could happen for validation across multiple parsed files) then the reported locations and printError output can be incorrect for the second node. This ensures locations are derived from nodes whenever possible to get correct location and amends comment documentation.
ref: graphql/graphql-js#1131
2018-02-13 10:42:51 +01:00
Daniel Tschinder
06c6c4bd97 Validate schema root types and directives
This moves validation out of GraphQLSchema's constructor (but not yet from other type constructors), which is responsible for root type validation and interface implementation checking.

Reduces time to construct GraphQLSchema significantly, shifting the time to validation.

This also allows for much looser rules within the schema builders, which implicitly validate while trying to adhere to flow types. Instead we use any casts to loosen the rules to defer that to validation where errors can be richer.

This also loosens the rule that a schema can only be constructed if it has a query type, moving that to validation as well. That makes flow typing slightly less nice, but allows for incremental schema building which is valuable

ref: graphql/graphql-js#1124
2018-02-13 10:42:35 +01:00
Daniel Tschinder
15374a31dd New: printError()
Lifted from / inspired by a similar change in graphql/graphql-js#722, this creates a new function `printError()` (and uses it as the implementation for `GraphQLError#toString()`) which prints location information in the context of an error.

This is moved from the syntax error where it used to be hard-coded, so it may now be used to format validation errors, value coercion errors, or any other error which may be associated with a location.

ref: graphql/graphql-js

BREAKING CHANGE: The SyntaxError message does not contain the codeframe anymore and only the message, (string) $error will print the codeframe.
2018-02-12 12:23:39 +01:00
Daniel Tschinder
f661f38215 Fix unhandled error when parsing custom scalar literals.
This factors out the enum value validation from scalar value validation and ensures the same try/catch is used in isValidLiteralValue as isValidPHPValue and protecting from errors in valueFromAST.
ref: graphql/graphql-js#1126
2018-02-11 22:31:04 +01:00
Daniel Tschinder
0c984a83bb Allow constructing GraphQLError with single node.
A common case is encountering an error which blames to a single AST node. Ensure the GraphQLError constructor can handle this case.

ref: graphql/graphql-js#1123
2018-02-11 21:18:54 +01:00
Daniel Tschinder
b5106a06c9 SDL Spec changes
This adds the recent changes to the SDL proposal.

ref: graphql/graphql-js#1117
2018-02-11 21:08:53 +01:00
Daniel Tschinder
74854d55a0 Read-only AST types
ref: graphql/graphql-js#1121
2018-02-11 18:28:34 +01:00
Daniel Tschinder
ff63e07b05 Improve introspection types + new getIntrospectionQuery()
This adds a new function `getIntrospectionQuery()` which allows for some minor configuration over the resulting query text: to exclude descriptions if your use case does not require them.

ref: graphql/graphql-js#1113
2018-02-11 18:19:52 +01:00
Daniel Tschinder
6e358eb26c Fix infinite loop on invalid queries in OverlappingFields
`OverlappingFieldsCanBeMerged` would infinite loop when passed something like

```graphql
fragment A on User {
  name
  ...A
}
```

It's not `OverlappingFieldsCanBeMerged`'s responsibility to detect that validation error, but we still would ideally avoid infinite looping.

This detects that case, and pretends that the infinite spread wasn't there for the purposes of this validation step.

Also, by memoizing and checking for self-references this removes duplicate reports.

ref: graphql/graphql-js#1111
2018-02-11 17:58:48 +01:00
Daniel Tschinder
7b05673d8d Validation: improving overlapping fields quality
This improves the overlapping fields validation performance and improves error reporting quality by separating the concepts of checking fields "within" a single collection of fields from checking fields "between" two different collections of fields. This ensures for deeply overlapping fields that nested fields are not checked against each other repeatedly. Extending this concept further, fragment spreads are no longer expanded inline before looking for conflicts, instead the fields within a fragment are compared to the fields with the selection set which contained the referencing fragment spread.

e.g.

```graphql
{
  same: a
  same: b
  ...X
}

fragment X on T {
  same: c
  same: d
}
```

In the above example, the initial query body is checked "within" so `a` is compared to `b`. Also, the fragment `X` is checked "within" so `c` is compared to `d`. Because of the fragment spread, the query body and fragment `X` are checked "between" so that `a` and `b` are each compared to `c` and `d`. In this trivial example, no fewer checks are performed, but in the case where fragments are referenced multiple times, this reduces the overall number of checks (regardless of memoization).

**BREAKING**: This can change the order of fields reported when a conflict arises when fragment spreads are involved. If you are checking the precise output of errors (e.g. for unit tests), you may find existing errors change from `"a" and "c" are different fields` to `"c" and "a" are different fields`.

From a perf point of view, this is fairly minor as the memoization "PairSet" was already keeping these repeated checks from consuming time, however this will reduce the number of memoized hits because of the algorithm improvement.

From an error reporting point of view, this reports nearest-common-ancestor issues when found in a fragment that comes later in the validation process. I've added a test which fails with the existing impl and now passes, as well as changed a comment.

This also fixes an error where validation issues could be missed because of an over-eager memoization. I've also modified the `PairSet` to be aware of both forms of memoization, also represented by a previously failing test.

ref: graphql/graphql-js#386
2018-02-11 17:45:35 +01:00
Daniel Tschinder
58453c31f7 Improve validation error message when field names conflict
ref: graphql/graphql-js#363
2018-02-11 14:11:21 +01:00
Daniel Tschinder
d70a9a5e53 Update to match SDL changes
This changes the parsing grammar and validation rules to more correctly implement the current state of the GraphQL SDL proposal (facebook/graphql#90)

ref: graphql/graphl-js#1102
2018-02-11 13:27:26 +01:00
Daniel Tschinder
0c32982171 Fix KnownDirectives validator to support all directives 2018-02-11 13:15:51 +01:00
Daniel Tschinder
1da3801614 Add predicates to for built-in types
ref: graphql/graphql-js#924
2018-02-10 18:45:52 +01:00
Daniel Tschinder
c4f11a577e Allow to extend GraphQL errors with additional properties
ref: graphql/graphql-js#928
2018-02-10 18:45:38 +01:00
Daniel Tschinder
2cbccb87db Remove duplicated code from buildASTSchema and extendSchema
ref: graphql/graphql-js#1000

BREAKING CHANGE: SchemaBuilder::build() and buildAST() and constructor
removed the typedecorator, as not needed anymore as library can now resolve
union and interfaces from generated schemas.
2018-02-10 18:45:32 +01:00
Daniel Tschinder
48c33302a8 (Potentially Breaking) Allow serializing scalars as null.
This changes the check for null/undefined to a check for undefined to determine if scalar serialization was successful or not, allowing `null` to be returned from serialize() without indicating error.

This is potentially breaking for any existing custom scalar which returned `null` from `serialize()` to indicate failure. To account for this change, it should either throw an error or return `undefined`.

ref: graphql/graphql-js#1104
2018-02-10 18:45:27 +01:00
Daniel Tschinder
27ce24b5fe Fix parsing of default values in build-schema
* Generalizes building a value from an AST, since "scalar" could be misleading, and supporting variable values within custom scalar literals can be valuable.
* Replaces isNullish with isInvalid since `null` is a meaningful value as a result of literal parsing.
* Provide reasonable default version of 'parseLiteral'

ref: 714ee980aa
ref: https://github.com/graphql/graphql-js/pull/903

# Conflicts:
#	src/Utils/BuildSchema.php
#	tests/Utils/BuildSchemaTest.php
2018-02-10 18:45:23 +01:00
Daniel Tschinder
2123946dbd Add warnings for nullable changes
ref: db4cfdc31d
ref: graphql/graphql-js#1096

# Conflicts:
#	tests/Utils/FindBreakingChangesTest.php
2018-02-10 18:45:18 +01:00
Daniel Tschinder
17a8c26fc9 Simplify operationTypes validation
ref: graphql/graphql-js#999

# Conflicts:
#	src/Utils/BuildSchema.php
2018-02-10 18:45:14 +01:00
Daniel Tschinder
1fdb3da7fb Remove notes about subscription being experimental
ref: graphql/graphql-js#bf4a25a33a62280e82680518adc279e34ec816e0
2018-02-10 18:45:10 +01:00
Daniel Tschinder
4e26de3588 Support for union types when using buildSchema
* Adds support for resolving union/interface types when using a generated schema
* Move resolveType __typename checking into defaultResolveType
* Clean up existing tests and improve error messages

ref: graphql/graphql-js#947

# Conflicts:
#	src/Utils/BuildSchema.php
#	tests/Utils/BuildSchemaTest.php
2018-02-10 18:45:01 +01:00
Daniel Tschinder
7705e50e44 Fix print of block string with leading space and quotation
ref: graphql/graphql-js#1190
2018-02-10 18:44:56 +01:00
Daniel Tschinder
022c490011 RFC: Descriptions as strings
As discussed in facebook/graphql#90

This proposes replacing leading comment blocks as descriptions in the schema definition language with leading strings (typically block strings).

While I think there is some reduced ergonomics of using a string literal instead of a comment to write descriptions (unless perhaps you are accustomed to Python or Clojure), there are some compelling advantages:

* Descriptions are first-class in the AST of the schema definition language.
* Comments can remain "ignored" characters.
* No ambiguity between commented out regions and descriptions.

Specific to this reference implementation, since this is a breaking change and comment descriptions in the experimental SDL have fairly wide usage, I've left the comment description implementation intact and allow it to be enabled via an option. This should help with allowing upgrading with minimal impact on existing codebases and aid in automated transforms.

BREAKING CHANGE: This does not parse descriptions from comments by default anymore and the value of description in Nodes changed from string to StringValueNode
2018-02-10 18:44:51 +01:00
Daniel Tschinder
e65638f6f4 Improvements to printing block strings
ref: graphql/graphql-js#f9e67c403a4667372684ee8c3e82e1f0ba27031b
2018-02-10 18:44:45 +01:00
Daniel Tschinder
8747ff8954 RFC: Block String
This RFC adds a new form of `StringValue`, the multi-line string, similar to that found in Python and Scala.

A multi-line string starts and ends with a triple-quote:

```
"""This is a triple-quoted string
and it can contain multiple lines"""
```

Multi-line strings are useful for typing literal bodies of text where new lines should be interpretted literally. In fact, the only escape sequence used is `\"""` and `\` is otherwise allowed unescaped. This is beneficial when writing documentation within strings which may reference the back-slash often:

```
"""
In a multi-line string \n and C:\\ are unescaped.
"""
```

The primary value of multi-line strings are to write long-form input directly in query text, in tools like GraphiQL, and as a prerequisite to another pending RFC to allow docstring style documentation in the Schema Definition Language.

Ref: graphql/graphql-js#926
2018-02-10 18:43:26 +01:00
Daniel Tschinder
46816a7cda Uniform parsing of queries with short-hand syntax with regular queries 2018-02-09 14:33:04 +01:00
Daniel Tschinder
eb9ac66af8 Fix how TypeInfo handles inline fragments without type
ref: graphql/graphql-js#1041
2018-02-09 14:32:44 +01:00
Jeremiah VALERIE
944ccebc08
Fix Utils::printSafe with bool true 2018-02-02 08:18:46 +01:00
Jiri Pokorny
dca2091351 Fix content-type header match when parsing PSR request. 2018-01-21 21:02:43 +01:00
Vladimir Razuvaev
4f223ba11d Fixed PSR request parsing, broken after recent changes 2018-01-13 18:08:07 +07:00
Vladimir Razuvaev
918bbff2bd
Merge branch 'master' into no-parsing 2018-01-13 17:20:00 +07:00
Vladimir Razuvaev
9944a689bf Exclude nulls from serialized AST 2018-01-13 16:25:06 +07:00
Vladimir Razuvaev
8b17953fe5 Fixed bug preventing use of parser noLocation option for serialization / deserialization 2018-01-13 15:45:09 +07:00
Vladimir Razuvaev
7c3737609f Doc-block fix 2018-01-01 22:12:51 +07:00
Adrien Crivelli
178b179db3
Drop support non pre-parsed PSR-7 request body
This revert #202 (commit 9d37f4c) because trying to parse PSR-7 request
was a mistake. The whole point of PSR-7 is to allow for interoperability
and be able to use specialized libs for body parsing (amongst many other
things). Trying to parse ourselves would be opening a can of worm if/when
other content types have to be supported. It is more correct and future
safe to require that the body is parsed before being passed to GraphQL.
2017-12-21 15:01:57 +09:00
Jáchym Toušek
25e341e9d9
Allow objects with __toString in IDType 2017-12-12 08:56:03 +01:00
Vladimir Razuvaev
9c563d5c00
Merge pull request #199 from roippi/findbreakingchanges
port findBreakingChanges
2017-11-28 20:14:36 +07:00
Vladimir Razuvaev
0af2fe79f2 StandardServer: a bit more validation for parsed json PSR-7 request (related to #202) 2017-11-28 12:28:54 +07:00
Adrien Crivelli
11c9429fab
Support non pre-parsed PSR-7 request body
Because PSR-7 specification only specify that `getParsedBody()` **may**
return the parsed body for `application/json`, we cannot assume that it
is always the case. So if the value returned parsed body is an empty array,
it means we should try to parse it ourselves (`null` would mean no body at
all according to spec).

With this modification we try to used given parsed body, but fallback on
trying to parse the body if necessary. This leave the door open to custom
implementation of parsing if needed, while making it easier to use out of
the box.
2017-11-26 19:57:32 +09:00
Ben Roberts
533b8b8b5f testDetectsAdditionsToUnionType 2017-11-21 12:18:28 -05:00
Ben Roberts
c4ae03454a testFindDangerousArgChanges 2017-11-21 11:50:11 -05:00
Ben Roberts
dbccf9b196 testDetectsRemovalOfInterfaces 2017-11-20 14:39:06 -05:00
Ben Roberts
0fd5abc833 testDetectsAdditionOfFieldArg 2017-11-20 13:48:21 -05:00
Ben Roberts
42d8ac07f9 testDetectsFieldArgumentTypeChange 2017-11-20 12:52:49 -05:00
Ben Roberts
4ea6cbe839 bugfix var ref 2017-11-17 17:35:33 -05:00
Ben Roberts
fc9c5e85aa testDetectsRemovalOfFieldArgument 2017-11-17 17:18:26 -05:00
Ben Roberts
cac011246e testDetectsValuesRemovedFromEnum 2017-11-17 16:24:04 -05:00
Ben Roberts
98ce1ccc69 testDetectsIfTypeWasRemovedFromUnion 2017-11-17 16:08:44 -05:00
Ben Roberts
dde2747918 testDetectsNonNullFieldAddedToInputType 2017-11-17 15:56:53 -05:00
Ben Roberts
cf4cccf4d6 testShouldDetectInputFieldChanges 2017-11-17 15:43:16 -05:00
Ben Roberts
68dbcc9ca3 testShouldDetectFieldChangesAndDeletions test 2017-11-17 14:29:47 -05:00
Ben Roberts
b2b5d6f080 findTypesThatChangedKind test 2017-11-17 13:04:01 -05:00
Ben Roberts
d9ce567cc8 findRemovedTypes test 2017-11-17 11:21:05 -05:00
Ben Roberts
4207adc098 change fns to static 2017-11-17 10:54:18 -05:00
Ben Roberts
6bdb7b7f80 improve docstrings 2017-11-16 17:44:08 -05:00
Ben Roberts
af60f1ee4d finish mechanical conversions 2017-11-16 17:42:38 -05:00
Ben Roberts
a1325eeb3f top level API functions, docstrings 2017-11-16 15:53:20 -05:00
Ben Roberts
55f6d6cf47 interfaces and enums 2017-11-16 15:25:25 -05:00
Ben Roberts
6e95b81aee dangerous changes consts 2017-11-16 14:17:21 -05:00
Ben Roberts
e649ef307a couple more functions 2017-11-16 14:15:39 -05:00
Ben Roberts
3811181f49 some functions converted over 2017-11-16 13:53:01 -05:00
Ben Roberts
7aebf2dbf7 initial porting 2017-11-15 16:12:56 -05:00
Vladimir Razuvaev
1487741f37 Preserve description for custom scalars (#181) 2017-10-14 00:45:23 +07:00
Vladimir Razuvaev
f7248dec76 Ability to override internal types (using types option of Schema class) #174 2017-09-22 23:08:51 +07:00
Vladimir Razuvaev
c5efd1d65b Additional checks for possible fragment spreads 2017-09-20 19:06:04 +07:00
Vladimir Razuvaev
1e34982bda Additional tests for variable coercion + use printSafeJson vs printSafe for input variables 2017-09-20 18:40:45 +07:00
Vladimir Razuvaev
a1e06b2e61 Account for query offset in files for errors 2017-09-20 18:36:19 +07:00
Vladimir Razuvaev
6050af4e67 Add support for directives applied on IDL & Schema 2017-09-20 17:43:06 +07:00
Vladimir Razuvaev
5f5c8118c0 Fixed parseValue of StringType and IDType: (it should return null on invalid value, not throw) 2017-09-20 16:38:02 +07:00
Vladimir Razuvaev
2023b427ae Fixed failed integer test (only fails on some OSs and PHP versions) 2017-09-20 16:20:51 +07:00
Derek Lavigne
d22385cc93 Update query variable coercion to meet the rules outlined in the
specification.

The framework currently coerces query variables similar to the way it
treats output values, which means it attempts to coerce the value into
the field's corresponding data type regardless of the received value.
According to items 3f and 3g in section 6.1.2
(http://facebook.github.io/graphql/#sec-Validating-Requests) of
Facebook's GraphQL specification query variables should be coerced
according to their type's input coercion rules laid out in section
3.1.1 (http://facebook.github.io/graphql/#sec-Scalars). If the value
can not be coerced into the correct type according the the input
coercion rules for the type a query error should be thrown. This
ensures that client provided query variables were of the correct format
and will be a valid format and type by the time they are passed into an
implementing resolver.

This patch fixes the above issue by updating the way query variables
are sanitized during the process of parsing the query. It directly
follows the rules for scalar input coercion laid out by the
specification and throws query errors when a value that cannot be
coerced to the correct type is given. Tests for isValidPHPValue will
also be updated to ensure that it is doing the correct type checks on
Values::isValidPHPValue for the given type and value provided. A new
test case will also be added to test Values::getVariableValues and make
sure it is also enforcing the scalar input coercion rules and throwing
errors for invalid values.
2017-09-18 12:14:09 -04:00
Vladimir Razuvaev
6ff427d241 Server: do not raise an error when variables are passed as empty string (#156) 2017-08-30 23:26:45 +07:00
Vladimir Razuvaev
d95fb461ee Server: fixed constructor screwed during rebasing + restored tests for the server 2017-08-21 01:18:23 +07:00
Vladimir Razuvaev
a1652468f0 Fixed minor error in docblock comment 2017-08-21 00:19:07 +07:00
Vladimir Razuvaev
6fdcfd9bb0 Merge branch 'master' of https://github.com/webonyx/graphql-php into v0.10 2017-08-20 23:16:51 +07:00
Vladimir Razuvaev
90602b31ba Added link to docs for generic error about unique type instance (#149) 2017-08-20 22:28:17 +07:00
Vladimir Razuvaev
de791536ce Docblocks improvements 2017-08-20 22:10:13 +07:00
Vladimir Razuvaev
d5e3d08d85 Minor Executor tweaks 2017-08-20 20:09:55 +07:00
Vladimir Razuvaev
085516bdda Moved GraphQL\Language\AST\Node::fromArray to GraphQL\Utils\AST::fromArray 2017-08-20 19:50:44 +07:00
Vladimir Razuvaev
bd444752f8 Documentation and docblock improvements 2017-08-20 16:00:44 +07:00
Vladimir Razuvaev
71343f2f62 Server: Extracted method for emitting response 2017-08-20 02:32:50 +07:00
Vladimir Razuvaev
1b4f983f3f Improved docblock comments (suitable for reference docs generation) 2017-08-19 23:01:46 +07:00
Jeremiah VALERIE
1c143360ca Add hooks to helps promise completion with custom backend 2017-08-18 16:18:48 +02:00
Vladimir Razuvaev
203fddfe4e Abstract base class for validation rules 2017-08-18 20:56:04 +07:00
Vladimir Razuvaev
9499e5ae8e Suppressing Config deprecation warning in tests 2017-08-18 18:07:23 +07:00
Vladimir Razuvaev
2bfce65484 Fixed Parser docblock comments 2017-08-18 02:55:22 +07:00
Vladimir Razuvaev
83cc9132a0 Server: minor improvements 2017-08-18 02:54:35 +07:00
Vladimir Razuvaev
d578b8a22f Split sync and async facade methods 2017-08-18 01:49:10 +07:00
Vladimir Razuvaev
e52fe8c384 BuildSchema::build() now accepts DocumentNode as well 2017-08-17 20:33:36 +07:00
Vladimir Razuvaev
03629c1e3c Refactored error formatting (debugging part) 2017-08-17 18:49:17 +07:00
Vladimir Razuvaev
1d38643538 Ability to re-throw resolver exceptions 2017-08-17 03:01:23 +07:00
Vladimir Razuvaev
51e877bfba Improving docblock comments 2017-08-17 02:15:49 +07:00