Update GraphQL parser (#3605)

* Update GraphQL parser

Fixes #3601

This adds support for
- description as strings
- extending all the possible types
- block strings
- allow removing {} if there's no implementation for all graphql types

This is a breaking change but shouldn't be a big issue.
- Empty types are no longer allowed (there's an option to enable it but it hasn't been released yet). The fix is to remove `{}`

Something that hasn't been changed because not released:
- Doesn't support the new `&` separator for implementing multiple interfaces

A bug has been fixed:
- Now properly prints @directives for unions.

* Properly handle triple quotes
master
Christopher Chedeau 2017-12-31 16:45:06 +01:00 committed by GitHub
parent 51744e1008
commit 58e5536741
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 571 additions and 108 deletions

View File

@ -33,7 +33,7 @@
"flow-parser": "0.59.0", "flow-parser": "0.59.0",
"get-stream": "3.0.0", "get-stream": "3.0.0",
"globby": "6.1.0", "globby": "6.1.0",
"graphql": "0.10.5", "graphql": "0.12.3",
"ignore": "3.3.7", "ignore": "3.3.7",
"jest-docblock": "21.3.0-beta.11", "jest-docblock": "21.3.0-beta.11",
"jest-validate": "21.1.0", "jest-validate": "21.1.0",

View File

@ -31,9 +31,11 @@ function genericPrint(path, options, print) {
]); ]);
} }
case "OperationDefinition": { case "OperationDefinition": {
const hasOperation = options.originalText[util.locStart(n)] !== "{";
const hasName = !!n.name;
return concat([ return concat([
n.name === null ? "" : n.operation, hasOperation ? n.operation : "",
n.name ? concat([" ", path.call(print, "name")]) : "", hasOperation && hasName ? concat([" ", path.call(print, "name")]) : "",
n.variableDefinitions && n.variableDefinitions.length n.variableDefinitions && n.variableDefinitions.length
? group( ? group(
concat([ concat([
@ -53,7 +55,7 @@ function genericPrint(path, options, print) {
) )
: "", : "",
printDirectives(path, print, n), printDirectives(path, print, n),
n.selectionSet ? (n.name === null ? "" : " ") : "", n.selectionSet ? (!hasOperation && !hasName ? "" : " ") : "",
path.call(print, "selectionSet") path.call(print, "selectionSet")
]); ]);
} }
@ -123,6 +125,11 @@ function genericPrint(path, options, print) {
return n.value; return n.value;
} }
case "StringValue": { case "StringValue": {
if (n.block) {
// It is not possible to distinguish between """\nabc\n""" and """abc"""
// https://github.com/graphql/graphql-js/issues/1188
return options.originalText.slice(util.locStart(n), util.locEnd(n));
}
return concat(['"', n.value.replace(/["\\]/g, "\\$&"), '"']); return concat(['"', n.value.replace(/["\\]/g, "\\$&"), '"']);
} }
case "IntValue": case "IntValue":
@ -231,31 +238,37 @@ function genericPrint(path, options, print) {
return concat(["extend ", path.call(print, "definition")]); return concat(["extend ", path.call(print, "definition")]);
} }
case "ObjectTypeExtension":
case "ObjectTypeDefinition": { case "ObjectTypeDefinition": {
return concat([ return concat([
path.call(print, "description"),
n.description ? hardline : "",
n.kind === "ObjectTypeExtension" ? "extend " : "",
"type ", "type ",
path.call(print, "name"), path.call(print, "name"),
n.interfaces.length > 0 n.interfaces.length > 0
? concat([" implements ", join(", ", path.map(print, "interfaces"))]) ? concat([" implements ", join(", ", path.map(print, "interfaces"))])
: "", : "",
printDirectives(path, print, n), printDirectives(path, print, n),
" {",
n.fields.length > 0 n.fields.length > 0
? indent( ? concat([
concat([ " {",
hardline, indent(
join( concat([
hardline, hardline,
path.call( join(
fieldsPath => printSequence(fieldsPath, options, print), hardline,
"fields" path.call(
fieldsPath => printSequence(fieldsPath, options, print),
"fields"
)
) )
) ])
]) ),
) hardline,
: "", "}"
hardline, ])
"}" : ""
]); ]);
} }
@ -291,6 +304,8 @@ function genericPrint(path, options, print) {
case "DirectiveDefinition": { case "DirectiveDefinition": {
return concat([ return concat([
path.call(print, "description"),
n.description ? hardline : "",
"directive ", "directive ",
"@", "@",
path.call(print, "name"), path.call(print, "name"),
@ -319,28 +334,35 @@ function genericPrint(path, options, print) {
]); ]);
} }
case "EnumTypeExtension":
case "EnumTypeDefinition": { case "EnumTypeDefinition": {
return concat([ return concat([
path.call(print, "description"),
n.description ? hardline : "",
n.kind === "EnumTypeExtension" ? "extend " : "",
"enum ", "enum ",
path.call(print, "name"), path.call(print, "name"),
printDirectives(path, print, n), printDirectives(path, print, n),
" {",
n.values.length > 0 n.values.length > 0
? indent( ? concat([
concat([ " {",
hardline, indent(
join( concat([
hardline, hardline,
path.call( join(
valuesPath => printSequence(valuesPath, options, print), hardline,
"values" path.call(
valuesPath => printSequence(valuesPath, options, print),
"values"
)
) )
) ])
]) ),
) hardline,
: "", "}"
hardline, ])
"}" : ""
]); ]);
} }
@ -361,28 +383,34 @@ function genericPrint(path, options, print) {
]); ]);
} }
case "InputObjectTypeExtension":
case "InputObjectTypeDefinition": { case "InputObjectTypeDefinition": {
return concat([ return concat([
path.call(print, "description"),
n.description ? hardline : "",
n.kind === "InputObjectTypeExtension" ? "extend " : "",
"input ", "input ",
path.call(print, "name"), path.call(print, "name"),
printDirectives(path, print, n), printDirectives(path, print, n),
" {",
n.fields.length > 0 n.fields.length > 0
? indent( ? concat([
concat([ " {",
hardline, indent(
join( concat([
hardline, hardline,
path.call( join(
fieldsPath => printSequence(fieldsPath, options, print), hardline,
"fields" path.call(
fieldsPath => printSequence(fieldsPath, options, print),
"fields"
)
) )
) ])
]) ),
) hardline,
: "", "}"
hardline, ])
"}" : ""
]); ]);
} }
@ -418,28 +446,35 @@ function genericPrint(path, options, print) {
]); ]);
} }
case "InterfaceTypeExtension":
case "InterfaceTypeDefinition": { case "InterfaceTypeDefinition": {
return concat([ return concat([
path.call(print, "description"),
n.description ? hardline : "",
n.kind === "InterfaceTypeExtension" ? "extend " : "",
"interface ", "interface ",
path.call(print, "name"), path.call(print, "name"),
printDirectives(path, print, n), printDirectives(path, print, n),
" {",
n.fields.length > 0 n.fields.length > 0
? indent( ? concat([
concat([ " {",
hardline, indent(
join( concat([
hardline, hardline,
path.call( join(
fieldsPath => printSequence(fieldsPath, options, print), hardline,
"fields" path.call(
fieldsPath => printSequence(fieldsPath, options, print),
"fields"
)
) )
) ])
]) ),
) hardline,
: "", "}"
hardline, ])
"}" : ""
]); ]);
} }
@ -463,25 +498,42 @@ function genericPrint(path, options, print) {
]); ]);
} }
case "UnionTypeExtension":
case "UnionTypeDefinition": { case "UnionTypeDefinition": {
return group( return group(
concat([ concat([
"union ", path.call(print, "description"),
path.call(print, "name"), n.description ? hardline : "",
" =", group(
ifBreak("", " "),
indent(
concat([ concat([
ifBreak(concat([line, " "])), n.kind === "UnionTypeExtension" ? "extend " : "",
join(concat([line, "| "]), path.map(print, "types")) "union ",
path.call(print, "name"),
printDirectives(path, print, n),
n.types.length > 0
? concat([
" =",
ifBreak("", " "),
indent(
concat([
ifBreak(concat([line, " "])),
join(concat([line, "| "]), path.map(print, "types"))
])
)
])
: ""
]) ])
) )
]) ])
); );
} }
case "ScalarTypeExtension":
case "ScalarTypeDefinition": { case "ScalarTypeDefinition": {
return concat([ return concat([
path.call(print, "description"),
n.description ? hardline : "",
n.kind === "ScalarTypeExtension" ? "extend " : "",
"scalar ", "scalar ",
path.call(print, "name"), path.call(print, "name"),
printDirectives(path, print, n) printDirectives(path, print, n)

View File

@ -1,23 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`directive_decl.graphql 1`] = ` exports[`directive_decl.graphql 1`] = `
directive @a on FIELD1 directive @a on QUERY
directive @a(as: String) on FIELD1 directive @a(as: String) on QUERY
directive @a(as: String = 1) on FIELD1 directive @a(as: String = 1) on QUERY
directive @a(as: String, b: Int!) on FIELD1 directive @a(as: String, b: Int!) on QUERY
directive @a(as: String! = 1 @deprecated) on FIELD1 directive @a(as: String! = 1 @deprecated) on QUERY
directive @a(as: String! = 1 @deprecated) on FIELD1 | FIELD2 directive @a(as: String! = 1 @deprecated) on QUERY | MUTATION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
directive @a on FIELD1 directive @a on QUERY
directive @a(as: String) on FIELD1 directive @a(as: String) on QUERY
directive @a(as: String = 1) on FIELD1 directive @a(as: String = 1) on QUERY
directive @a(as: String, b: Int!) on FIELD1 directive @a(as: String, b: Int!) on QUERY
directive @a(as: String! = 1 @deprecated) on FIELD1 directive @a(as: String! = 1 @deprecated) on QUERY
directive @a(as: String! = 1 @deprecated) on FIELD1 | FIELD2 directive @a(as: String! = 1 @deprecated) on QUERY | MUTATION
`; `;

View File

@ -1,6 +1,6 @@
directive @a on FIELD1 directive @a on QUERY
directive @a(as: String) on FIELD1 directive @a(as: String) on QUERY
directive @a(as: String = 1) on FIELD1 directive @a(as: String = 1) on QUERY
directive @a(as: String, b: Int!) on FIELD1 directive @a(as: String, b: Int!) on QUERY
directive @a(as: String! = 1 @deprecated) on FIELD1 directive @a(as: String! = 1 @deprecated) on QUERY
directive @a(as: String! = 1 @deprecated) on FIELD1 | FIELD2 directive @a(as: String! = 1 @deprecated) on QUERY | MUTATION

View File

@ -1,6 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`kitchen_sink.graphql 1`] = ` exports[`kitchen_sink.graphql 1`] = `
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
query queryName($foo: ComplexType, $site: Site = MOBILE) { query queryName($foo: ComplexType, $site: Site = MOBILE) {
whoever123is: node(id: [123, 456]) { whoever123is: node(id: [123, 456]) {
id , id ,
@ -44,18 +49,21 @@ subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
} }
fragment frag on Friend { fragment frag on Friend {
foo(size: $size, bar: $b, obj: {key: "value"}) foo(size: $size, bar: $b, obj: {key: "value", block: """
block string uses \\"""
"""})
} }
{ {
unnamed(truthy: true, falsey: false, nullish: null), unnamed(truthy: true, falsey: false, nullish: null),
query query
} }
query {
field
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
query queryName($foo: ComplexType, $site: Site = MOBILE) { query queryName($foo: ComplexType, $site: Site = MOBILE) {
whoever123is: node(id: [123, 456]) { whoever123is: node(id: [123, 456]) {
id id
@ -99,7 +107,13 @@ subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
} }
fragment frag on Friend { fragment frag on Friend {
foo(size: $size, bar: $b, obj: { key: "value" }) foo(
size: $size
bar: $b
obj: { key: "value", block: """
block string uses \\"""
""" }
)
} }
{ {
@ -107,8 +121,243 @@ fragment frag on Friend {
query query
} }
query { `;
field
exports[`schema_kitchen_sink.graphql 1`] = `
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
schema {
query: QueryType
mutation: MutationType
} }
"""
This is a description
of the \`Foo\` type.
"""
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = {key: "value"}): Type
seven(argument: Int = null): Type
}
type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArg): Type @onField
}
type UndefinedType
extend type Foo {
seven(argument: [String]): Type
}
extend type Foo @onType
"""
This is a description
"""
interface Bar {
one: Type
four(argument: String = "string"): String
}
interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArg): Type @onField
}
interface UndefinedInterface
extend interface Bar {
two(argument: InputType!): Type
}
extend interface Bar @onInterface
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
union AnnotatedUnionTwo @onUnion = | A | B
union UndefinedUnion
extend union Feed = Photo | Video
extend union Feed @onUnion
scalar CustomScalar
scalar AnnotatedScalar @onScalar
extend scalar CustomScalar @onScalar
enum Site {
DESKTOP
MOBILE
}
enum AnnotatedEnum @onEnum {
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
}
enum UndefinedEnum
extend enum Site {
VR
}
extend enum Site @onEnum
input InputType {
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObject {
annotatedField: Type @onField
}
input UndefinedInput
extend input InputType {
other: Float = 1.23e4
}
extend input InputType @onInputObject
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!)
on FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT
directive @include2(if: Boolean!) on
| FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
schema {
query: QueryType
mutation: MutationType
}
"""
This is a description
of the \`Foo\` type.
"""
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = { key: "value" }): Type
seven(argument: Int = null): Type
}
type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArg): Type @onField
}
type UndefinedType
extend type Foo {
seven(argument: [String]): Type
}
extend type Foo @onType
"""
This is a description
"""
interface Bar {
one: Type
four(argument: String = "string"): String
}
interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArg): Type @onField
}
interface UndefinedInterface
extend interface Bar {
two(argument: InputType!): Type
}
extend interface Bar @onInterface
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
union AnnotatedUnionTwo @onUnion = A | B
union UndefinedUnion
extend union Feed = Photo | Video
extend union Feed @onUnion
scalar CustomScalar
scalar AnnotatedScalar @onScalar
extend scalar CustomScalar @onScalar
enum Site {
DESKTOP
MOBILE
}
enum AnnotatedEnum @onEnum {
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
}
enum UndefinedEnum
extend enum Site {
VR
}
extend enum Site @onEnum
input InputType {
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObject {
annotatedField: Type @onField
}
input UndefinedInput
extend input InputType {
other: Float = 1.23e4
}
extend input InputType @onInputObject
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include2(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
`; `;

View File

@ -1,3 +1,8 @@
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
query queryName($foo: ComplexType, $site: Site = MOBILE) { query queryName($foo: ComplexType, $site: Site = MOBILE) {
whoever123is: node(id: [123, 456]) { whoever123is: node(id: [123, 456]) {
id , id ,
@ -41,14 +46,12 @@ subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
} }
fragment frag on Friend { fragment frag on Friend {
foo(size: $size, bar: $b, obj: {key: "value"}) foo(size: $size, bar: $b, obj: {key: "value", block: """
block string uses \"""
"""})
} }
{ {
unnamed(truthy: true, falsey: false, nullish: null), unnamed(truthy: true, falsey: false, nullish: null),
query query
} }
query {
field
}

View File

@ -0,0 +1,120 @@
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
schema {
query: QueryType
mutation: MutationType
}
"""
This is a description
of the `Foo` type.
"""
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = {key: "value"}): Type
seven(argument: Int = null): Type
}
type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArg): Type @onField
}
type UndefinedType
extend type Foo {
seven(argument: [String]): Type
}
extend type Foo @onType
"""
This is a description
"""
interface Bar {
one: Type
four(argument: String = "string"): String
}
interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArg): Type @onField
}
interface UndefinedInterface
extend interface Bar {
two(argument: InputType!): Type
}
extend interface Bar @onInterface
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
union AnnotatedUnionTwo @onUnion = | A | B
union UndefinedUnion
extend union Feed = Photo | Video
extend union Feed @onUnion
scalar CustomScalar
scalar AnnotatedScalar @onScalar
extend scalar CustomScalar @onScalar
enum Site {
DESKTOP
MOBILE
}
enum AnnotatedEnum @onEnum {
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
}
enum UndefinedEnum
extend enum Site {
VR
}
extend enum Site @onEnum
input InputType {
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObject {
annotatedField: Type @onField
}
input UndefinedInput
extend input InputType {
other: Float = 1.23e4
}
extend input InputType @onInputObject
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!)
on FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT
directive @include2(if: Boolean!) on
| FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT

View File

@ -10,7 +10,7 @@ directive @dir(
arg2: String arg2: String
arg3: String arg3: String
) on Field ) on QUERY
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
directive @dir( directive @dir(
# comment # comment
@ -19,7 +19,7 @@ directive @dir(
# comment # comment
arg2: String arg2: String
arg3: String arg3: String
) on Field ) on QUERY
`; `;

View File

@ -7,4 +7,4 @@ directive @dir(
arg2: String arg2: String
arg3: String arg3: String
) on Field ) on QUERY

View File

@ -35,9 +35,11 @@ extend type Feedback {
exports[`implements.graphql 1`] = ` exports[`implements.graphql 1`] = `
type VRMConversation implements Node, Entity @foo { type VRMConversation implements Node, Entity @foo {
a: Int
} }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type VRMConversation implements Node, Entity @foo { type VRMConversation implements Node, Entity @foo {
a: Int
} }
`; `;

View File

@ -1,2 +1,3 @@
type VRMConversation implements Node, Entity @foo { type VRMConversation implements Node, Entity @foo {
a: Int
} }

View File

@ -2,9 +2,33 @@
exports[`string.graphql 1`] = ` exports[`string.graphql 1`] = `
query X($a: Int) @relay(meta: "{\\"lowPri\\": true}") { a } query X($a: Int) @relay(meta: "{\\"lowPri\\": true}") { a }
"""abc"""
type T {
a: Int
}
"""
abc
"""
type T {
a: Int
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
query X($a: Int) @relay(meta: "{\\"lowPri\\": true}") { query X($a: Int) @relay(meta: "{\\"lowPri\\": true}") {
a a
} }
"""abc"""
type T {
a: Int
}
"""
abc
"""
type T {
a: Int
}
`; `;

View File

@ -1 +1,13 @@
query X($a: Int) @relay(meta: "{\"lowPri\": true}") { a } query X($a: Int) @relay(meta: "{\"lowPri\": true}") { a }
"""abc"""
type T {
a: Int
}
"""
abc
"""
type T {
a: Int
}

View File

@ -2001,11 +2001,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
graphql@0.10.5: graphql@0.12.3:
version "0.10.5" version "0.12.3"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.12.3.tgz#11668458bbe28261c0dcb6e265f515ba79f6ce07"
dependencies: dependencies:
iterall "^1.1.0" iterall "1.1.3"
growly@^1.3.0: growly@^1.3.0:
version "1.3.0" version "1.3.0"
@ -2482,9 +2482,9 @@ istanbul-reports@^1.1.1:
dependencies: dependencies:
handlebars "^4.0.3" handlebars "^4.0.3"
iterall@^1.1.0: iterall@1.1.3:
version "1.1.1" version "1.1.3"
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.1.tgz#f7f0af11e9a04ec6426260f5019d9fcca4d50214" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9"
jest-changed-files@^21.2.0: jest-changed-files@^21.2.0:
version "21.2.0" version "21.2.0"