Changelog History
Page 19
-
v1.4.1 Changes
January 16, 2017๐ Bug fixes
- Absent variables aren't present in
args#479 - ๐ Fix grouped ActiveRecord relation with
lastonly #476 - 0๏ธโฃ
Schema#default_mask& queryonly:/except:are combined, not overriden #485 - Root types can be hidden with dynamic filters #480
- Absent variables aren't present in
-
v1.4.0 Changes
January 08, 2017๐ฅ Breaking changes
๐ Deprecations
- One-argument schema filters are deprecated. Schema filters are now called with two arguments,
(member, ctx). #463 To update, add a second argument to your schema filter. - โก๏ธ The arity of middleware
#callmethods has changed. Instead ofnext_middlewarebeing the last argument, it is passed as a block. To update, callyieldto continue the middleware chain or use&next_middlewareto capturenext_middlewareinto a local variable.
# Previous: def call(*args, next_middleware) next_middleware.call end # Current def call(*args) yield end # Or def call(*args, &next_middleware) next_middleware.call end๐ New features
- You can add a
nodesfield directly to a connection. #451 That way you can say{ friends { nodes } }instead of{ freinds { edges { node } } }. Either passnodes_field: truewhen defining a custom connection type, for example:
FriendsConnectionType = FriendType.define_connection(nodes_field: true)Or, set
GraphQL::Relay::ConnectionType.default_nodes_field = truebefore defining your schema, for example:GraphQL::Relay::ConnectionType.default_nodes_field = true MySchema = GraphQL::Schema.define { ... }- ๐ Middleware performance was dramatically improved by reducing object allocations. #462
next_middlewareis now passed as a block. In general,yieldis faster than calling a captured block. - ๐ Improve error messages for wrongly-typed variable values #423
- Cache the value of
resolve_typeper object per query #462 - Pass
ctxto schema filters #463 - Accept whitelist schema filters as
only:#463 - โ Add
Schema#to_definitionwhich acceptsonly:/except:to filter the schema when printing #463 - โ Add
Schema#default_maskas a defaultexcept:filter #463 - โ Add reflection methods to types #473
#introspection?marks built-in introspection types#default_scalar?marks built-in scalars#default_relay?marks built-in Relay types#default_directive?marks built-in directives
๐ Bug fixes
- ๐ Fix ArrayConnection: gracefully handle out-of-bounds cursors #452
- ๐ Fix ArrayConnection & RelationConnection: properly handle
lastwithoutbefore#362
- One-argument schema filters are deprecated. Schema filters are now called with two arguments,
-
v1.3.0 Changes
December 08, 2016๐ Deprecations
- ๐ As per the spec,
__prefix is reserved for built-in names only. This is currently deprecated and will be invalid in a future version. #427, #450
๐ New features
Schema#lazy_resolveallows you to define handlers for a second pass of resolution #386Field#lazy_resolvecan be instrumented to track lazy resolution #429Schema#type_errorallows you to handleInvalidNullErrors andUnresolvedTypeErrorsin your own way #416Schema#cursor_encodercan be specified for transforming cursors from built-in Connection implementations #345- Schema members
#dupcorrectly: they shallowly copy their state into new instances #444 Query#provided_variablesis now public #430
๐ Bug fixes
- Schemas created from JSON or strings with custom scalars can validate queries (although they still can't check if inputs are valid for those custom scalars) #445
- ๐ Always use
quirks_mode: truewhen serializing values (to support non-stdlibJSONs) #449 - Calling
#redefineon a Schema member copies state outside of previous#defineblocks (uses#dup) #444
- ๐ As per the spec,
-
v1.2.6 Changes
December 01, 2016๐ Bug fixes
- Preserve connection behaviors after
redefine#421 - Implement
respond_to_missing?onDefinedObjectProxy(which isselfinside.define { ... }) #414
- Preserve connection behaviors after
-
v1.2.5 Changes
November 22, 2016๐ฅ Breaking changes
Visitorreceived some breaking changes, though these are largely-private APIs (#401):- Global visitor hooks (
Visitor#enterandVisitor#leave) have been removed - Returning
SKIPfrom a visitor hook no longer skips sibling nodes
- Global visitor hooks (
๐ New features
Schema#instrumentmay be called outside ofSchema.define#399- Validation: assert that directives on a node are unique #409
instrument(:query)hooks are executed even if the query raises an error #412
๐ Bug fixes
Mutation#input_fieldsshould trigger lazy definition #392ObjectType#connectiondoesn't modify the providedGraphQL::Field#411Mutation#resolvemay return aGraphQL::ExecutionError#405Argumentscan handle nullable arguments passed asnil#410
-
v1.2.4 Changes
November 14, 2016๐ Bug fixes
- ๐จ For invalid enum values, print the enum name in the error message (not a Ruby object dump) #403
- ๐ Improve detection of invalid UTF-8 escapes #394
-
v1.2.3 Changes
November 14, 2016๐ Bug fixes
Lexerprevious token should be a local variable, not a method attribute #396Argumentsshould wrap values according to their type, not their value #398
-
v1.2.2 Changes
November 07, 2016๐ New features
Schema.executeraises an error ifvariables:is a string
๐ Bug fixes
- Dynamic fields
__schema,__typeand__typenameare properly validated #391
-
v1.2.1 Changes
November 07, 2016๐ Bug fixes
- ๐ Implement
Query::Context#strategyandFieldResolutionContext#strategyto support GraphQL::Batch #382
- ๐ Implement
-
v1.2.0 Changes
November 07, 2016๐ฅ Breaking changes
A breaking change from 1.1.0 was reverted: two-character
"\\u"is longer treated as the Unicode escape character #372Due to the execution bug described below, the internal representation of a query has changed. Although
Noderesponds to the same methods, tree is built differently and query analyzers visit it differently. #373, #379
The difference is in cases like this:
outer { ... on A { inner1 { inner2 } } ... on B { inner1 { inner3 } } }Previously, visits would be:
outer, which has one child:inner1, which has two definitions (one onA, another onB), then visit its twochildren:inner2which has one definition (on the return type ofinner1)inner3which has one definition (on the return type ofinner1)
This can be wrong for some cases. For example, if
AandBare mutually exclusive (both object types, or union types with no shared members), theninner2andinner3will never be executed together.Now, the visit goes like this:
outerwhich has two entries intyped_children, one onAand another onB. Visit eachtyped_chidrenbranch:inner1, then its onetyped_childrenbranch:inner2
inner1, then its onetyped_childrenbranch:inner3
As you can see, we visit
inner1twice, once for each type condition.inner2andinner3are no longer visited as siblings. Instead they're visited as ... cousins? (They share a grandparent, not a parent.)Although
Node#childrenis still present, it may not contain all children actually resolved at runtime, since multipletyped_childrenbranches could apply to the same runtime type (eg, two branches on interface types can apply to the same object type). To track all children, you have to do some bookkeeping during visitation, seeQueryComplexityfor an example.You can see PR #373 for how built-in analyzers were changed to reflect this.
๐ Deprecations
- ๐
InternalRepresentation::Node#childrenandInternalRepresentation::Node#definitionsare deprecated due to the bug described below and the breaking change described above. Instead, useInternalRepresentation::Node#typed_childrenandInternalRepresentation::Node#defininition. #373
๐ New features
0๏ธโฃ
nullsupport for the whole library: as a query literal, variable value, and argument default value. To check for the presence of a nullable, useArguments#key?#369GraphQL::Schema::UniqueWithinType.default_id_separatormay be assigned to a custom value #381Context#add_error(err)may be used to add aGraphQL::ExecutionErrorto the response's"errors"key (and the resolve function can still return a value) #367The third argument of
resolveis now aFieldResolutionContext, which behaves just like aQuery::Context, except that it is not modified during query execution. This means you can capture a reference to that context and access some field-level details after the fact:#path,#ast_node,#irep_node. (Other methods are delegated to the underlyingQuery::Context) #379TimeoutMiddleware's second argument is a proxied query object: it's#contextmethod returns theFieldResolutionContext(see above) for the timed-out field. Other methods are delegated to the underlyingQuery#379
๐ Bug fixes
- ๐ Fix deep selection merging on divergently-typed fragments. #370, #373, #379 Previously, nested selections on different fragments were not distinguished. Consider a case like this:
... on A { inner1 { inner2 } } ... on B { inner1 { inner3 } }Previously, an object of type
Awould resolveinner1, then the result would receive bothinner2andinner3. The same was true for an object of typeB.Now, those are properly distinguished. An object of type
Aresolvesinner1, then its result receivesinner2. An object of typeBreceivesinner1, theninner3.