Skip to content

Commit

Permalink
add specifiedBy directive (graph-gophers#532)
Browse files Browse the repository at this point in the history
  • Loading branch information
benzolium authored and KNiepok committed Feb 28, 2023
1 parent 1b1fb0b commit 4632db3
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 10 deletions.
37 changes: 36 additions & 1 deletion example/social/introspect.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,29 @@
"INLINE_FRAGMENT"
],
"name": "skip"
},
{
"args": [
{
"defaultValue": null,
"description": "The URL should point to a human-readable specification of the data format, serialization, and coercion rules.",
"name": "url",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
],
"description": "Provides a scalar specification URL for specifying the behavior of custom scalar types.",
"locations": [
"SCALAR"
],
"name": "specifiedBy"
}
],
"mutationType": null,
Expand Down Expand Up @@ -1339,6 +1362,18 @@
"name": "__Type",
"ofType": null
}
},
{
"args": [],
"deprecationReason": null,
"description": null,
"isDeprecated": false,
"name": "specifiedByURL",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
],
"inputFields": null,
Expand Down Expand Up @@ -1408,4 +1443,4 @@
}
]
}
}
}
37 changes: 36 additions & 1 deletion example/starwars/introspect.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,29 @@
"INLINE_FRAGMENT"
],
"name": "skip"
},
{
"args": [
{
"defaultValue": null,
"description": "The URL should point to a human-readable specification of the data format, serialization, and coercion rules.",
"name": "url",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
],
"description": "Provides a scalar specification URL for specifying the behavior of custom scalar types.",
"locations": [
"SCALAR"
],
"name": "specifiedBy"
}
],
"mutationType": {
Expand Down Expand Up @@ -1981,6 +2004,18 @@
"name": "__Type",
"ofType": null
}
},
{
"args": [],
"deprecationReason": null,
"description": null,
"isDeprecated": false,
"name": "specifiedByURL",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
],
"inputFields": null,
Expand Down Expand Up @@ -2050,4 +2085,4 @@
}
]
}
}
}
70 changes: 62 additions & 8 deletions graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ func TestEmbeddedStruct(t *testing.T) {
type Query {
course: Course!
}
type Course {
name: String!
createdAt: String!
Expand Down Expand Up @@ -1495,6 +1495,40 @@ func TestDeprecatedDirective(t *testing.T) {
})
}

func TestSpecifiedByDirective(t *testing.T) {
gqltesting.RunTests(t, []*gqltesting.Test{
{
Schema: graphql.MustParseSchema(`
schema {
query: Query
}
type Query {
}
scalar UUID @specifiedBy(
url: "https://tools.ietf.org/html/rfc4122"
)
`, &struct{}{}),
Query: `
query {
__type(name: "UUID") {
name
specifiedByURL
}
}
`,
Variables: map[string]interface{}{},
ExpectedResult: `
{
"__type": {
"name": "UUID",
"specifiedByURL": "https://tools.ietf.org/html/rfc4122"
}
}
`,
},
})
}

type testBadEnumResolver struct{}

func (r *testBadEnumResolver) Hero() *testBadEnumCharacterResolver {
Expand Down Expand Up @@ -1855,11 +1889,11 @@ func TestTypeName(t *testing.T) {
}
}
}
fragment Droid on Droid {
name
__typename
}
}
`,
RawResponse: true,
ExpectedResult: `{"hero":{"__typename":"Droid","name":"R2-D2"}}`,
Expand Down Expand Up @@ -2479,6 +2513,26 @@ func TestIntrospection(t *testing.T) {
}
}
]
},
{
"name": "specifiedBy",
"description": "Provides a scalar specification URL for specifying the behavior of custom scalar types.",
"locations": [
"SCALAR"
],
"args": [
{
"name": "url",
"description": "The URL should point to a human-readable specification of the data format, serialization, and coercion rules.",
"type": {
"kind": "NON_NULL",
"ofType": {
"kind": "SCALAR",
"name": "String"
}
}
}
]
}
]
}
Expand Down Expand Up @@ -3801,7 +3855,7 @@ func TestPanicAmbiguity(t *testing.T) {
name: String!
university: University!
}
type University {
name: String!
}
Expand Down Expand Up @@ -4347,11 +4401,11 @@ func TestQueryVariablesValidation(t *testing.T) {
required: String!
optional: String
}
type SearchResults {
match: String
}
type Query {
search(filter: SearchFilter!): [SearchResults!]!
}`, &queryVarResolver{}, graphql.UseFieldResolvers()),
Expand All @@ -4372,11 +4426,11 @@ func TestQueryVariablesValidation(t *testing.T) {
required: String!
optional: String
}
type SearchResults {
match: String
}
type Query {
search(filter: SearchFilter!): [SearchResults!]!
}`, &queryVarResolver{}, graphql.UseFieldResolvers()),
Expand Down
7 changes: 7 additions & 0 deletions internal/schema/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ var metaSrc = `
reason: String = "No longer supported"
) on FIELD_DEFINITION | ENUM_VALUE
# Provides a scalar specification URL for specifying the behavior of custom scalar types.
directive @specifiedBy(
# The URL should point to a human-readable specification of the data format, serialization, and coercion rules.
url: String!
) on SCALAR
# A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
#
# In some cases, you need to provide options to alter GraphQL's execution behavior
Expand Down Expand Up @@ -179,6 +185,7 @@ var metaSrc = `
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
inputFields: [__InputValue!]
ofType: __Type
specifiedByURL: String
}
# An enum describing what kind of type a given ` + "`" + `__Type` + "`" + ` is.
Expand Down
14 changes: 14 additions & 0 deletions introspection/introspection.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,20 @@ func (r *Type) OfType() *Type {
}
}

func (r *Type) SpecifiedByURL() *string {
switch t := r.typ.(type) {
case *types.ScalarTypeDefinition:
if d := t.Directives.Get("specifiedBy"); d != nil {
arg := d.Arguments.MustGet("url")
url := arg.Deserialize(nil).(string)
return &url
}
default:
return nil
}
return nil
}

type Field struct {
field *types.FieldDefinition
}
Expand Down

0 comments on commit 4632db3

Please sign in to comment.