Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__type field #163

Merged
merged 3 commits into from
Aug 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions graphql-async/test/async_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ open Async_kernel
open Async_unix

let yojson = (module struct
type t = Yojson.Basic.json
type t = Yojson.Basic.json [@@warning "-3"]

let pp formatter t =
Format.pp_print_text formatter (Yojson.Basic.pretty_to_string t)

let equal = (=)
end : Alcotest.TESTABLE with type t = Yojson.Basic.json)
end : Alcotest.TESTABLE with type t = Yojson.Basic.json) [@@warning "-3"]

let test_query schema ctx query expected =
Thread_safe.block_on_async_exn begin fun () ->
Expand Down
4 changes: 2 additions & 2 deletions graphql-lwt/test/lwt_test.ml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
open Lwt

let yojson = (module struct
type t = Yojson.Basic.json
type t = Yojson.Basic.json [@@warning "-3"]

let pp formatter t =
Format.pp_print_text formatter (Yojson.Basic.pretty_to_string t)

let equal = (=)
end : Alcotest.TESTABLE with type t = Yojson.Basic.json)
end : Alcotest.TESTABLE with type t = Yojson.Basic.json) [@@warning "-3"]

let test_query schema ctx query expected =
Lwt_main.run begin
Expand Down
76 changes: 47 additions & 29 deletions graphql/src/graphql_schema.ml
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,18 @@ module Introspection = struct
| DefaultArg a -> arg_types memo a.typ
in arg_list_types memo' args

let types_of_schema s =
let types, _ =
List.fold_left
(fun memo op ->
match op with
| None -> memo
| Some op -> types ~memo (Object op))
([], StringSet.empty)
[Some s.query; s.mutation; Option.map s.subscription ~f:obj_of_subscription_obj]
in
types

let rec args_to_list : type a b. ?memo:any_arg list -> (a, b) Arg.arg_list -> any_arg list = fun ?memo:(memo=[]) arglist ->
let open Arg in
match arglist with
Expand Down Expand Up @@ -1134,7 +1146,7 @@ module Introspection = struct
]
}

let __schema : 'ctx. ('ctx, 'ctx schema option) typ = Object {
let __schema : 'ctx. ('ctx, ('ctx schema * any_typ list) option) typ = Object {
name = "__Schema";
doc = None;
abstracts = no_abstracts;
Expand All @@ -1146,16 +1158,7 @@ module Introspection = struct
typ = NonNullable (List (NonNullable __type));
args = Arg.[];
lift = Io.ok;
resolve = fun _ s ->
let types, _ = List.fold_left
(fun memo op ->
match op with
| None -> memo
| Some op -> types ~memo (Object op))
([], StringSet.empty)
[Some s.query; s.mutation; Option.map s.subscription ~f:obj_of_subscription_obj]
in
types
resolve = fun _ (_schema, types) -> types
};
Field {
name = "queryType";
Expand All @@ -1164,7 +1167,7 @@ module Introspection = struct
typ = NonNullable __type;
args = Arg.[];
lift = Io.ok;
resolve = fun _ s -> AnyTyp (Object s.query)
resolve = fun _ (schema, _types) -> AnyTyp (Object schema.query)
};
Field {
name = "mutationType";
Expand All @@ -1173,7 +1176,7 @@ module Introspection = struct
typ = __type;
args = Arg.[];
lift = Io.ok;
resolve = fun _ s -> Option.map s.mutation ~f:(fun mut -> AnyTyp (Object mut))
resolve = fun _ (schema, _types) -> Option.map schema.mutation ~f:(fun mut -> AnyTyp (Object mut))
};
Field {
name = "subscriptionType";
Expand All @@ -1182,8 +1185,8 @@ module Introspection = struct
typ = __type;
args = Arg.[];
lift = Io.ok;
resolve = fun _ s ->
Option.map s.subscription ~f:(fun subs -> AnyTyp (Object (obj_of_subscription_obj subs)))
resolve = fun _ (schema, _types) ->
Option.map schema.subscription ~f:(fun subs -> AnyTyp (Object (obj_of_subscription_obj subs)))
};
Field {
name = "directives";
Expand All @@ -1193,31 +1196,46 @@ module Introspection = struct
args = Arg.[];
lift = Io.ok;
resolve = fun _ _ -> []
};
Field {
name = "subscriptionType";
doc = None;
deprecated = NotDeprecated;
typ = __type;
args = Arg.[];
lift = Io.ok;
resolve = fun _ _ -> None
}
]
}

let add_schema_field s =
let add_built_in_fields schema =
let types = types_of_schema schema in
let schema_field = Field {
name = "__schema";
doc = None;
deprecated = NotDeprecated;
typ = NonNullable __schema;
args = Arg.[];
lift = Io.ok;
resolve = fun _ _ -> s
resolve = fun _ _ -> (schema, types)
} in
let type_field = Field {
name = "__type";
doc = None;
deprecated = NotDeprecated;
typ = __type;
args = Arg.[arg "name" ~typ:(non_null string)];
lift = Io.ok;
resolve = fun _ _ name ->
List.find (fun typ ->
match typ with
| AnyTyp (Object o) -> o.name = name
| AnyTyp (Scalar s) -> s.name = name
| AnyTyp (Enum e) -> e.name = name
| AnyTyp (Abstract a) -> a.name = name
| AnyTyp (List _) -> false
| AnyTyp (NonNullable _) -> false
| AnyArgTyp (Arg.Object o) -> o.name = name
| AnyArgTyp (Arg.Scalar s) -> s.name = name
| AnyArgTyp (Arg.Enum e) -> e.name = name
| AnyArgTyp (Arg.List _) -> false
| AnyArgTyp (Arg.NonNullable _) -> false
) types
} in
let fields = lazy (schema_field::(Lazy.force s.query.fields)) in
{ s with query = { s.query with fields } }
let fields = lazy (schema_field::type_field::(Lazy.force schema.query.fields)) in
{ schema with query = { schema.query with fields } }
end

(* Execution *)
Expand Down Expand Up @@ -1579,7 +1597,7 @@ end
let open Io.Infix in
let execute' schema ctx doc =
Io.return (collect_and_validate_fragments doc) >>=? fun fragments ->
let schema' = Introspection.add_schema_field schema in
let schema' = Introspection.add_built_in_fields schema in
Io.return (select_operation ?operation_name doc) >>=? fun op ->
let default_variables = List.fold_left (fun memo { Graphql_parser.name; default_value; _ } ->
match default_value with
Expand Down
32 changes: 27 additions & 5 deletions graphql/test/introspection_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ open Graphql
let test_query schema query = Test_common.test_query schema () query

let suite = [
("not deprecated", `Quick, fun () ->
("__schema: not deprecated", `Quick, fun () ->
let schema = Schema.(schema [
field "not-deprecated"
~deprecated:NotDeprecated
Expand All @@ -27,7 +27,7 @@ let suite = [
]
])
);
("default deprecation", `Quick, fun () ->
("__schema: default deprecation", `Quick, fun () ->
let schema = Schema.(schema [
field "default"
~typ:string
Expand All @@ -50,7 +50,7 @@ let suite = [
]
])
);
("deprecated-without-reason", `Quick, fun () ->
("__schema: deprecated-without-reason", `Quick, fun () ->
let schema = Schema.(schema [
field "deprecated-without-reason"
~deprecated:(Deprecated None)
Expand All @@ -74,7 +74,7 @@ let suite = [
]
])
);
("deprecated with reason", `Quick, fun () ->
("__schema: deprecated with reason", `Quick, fun () ->
let schema = Schema.(schema [
field "deprecated-with-reason"
~deprecated:(Deprecated (Some "deprecation reason"))
Expand All @@ -98,7 +98,7 @@ let suite = [
]
])
);
("deduplicates argument types", `Quick, fun () ->
("__schema: deduplicates argument types", `Quick, fun () ->
let schema = Schema.(schema [
field "sum"
~typ:(non_null int)
Expand All @@ -124,4 +124,26 @@ let suite = [
]
])
);
("__type", `Quick, fun () ->
let query = {|
{
role_type: __type(name: "role") {
name
}
user_type: __type(name: "user") {
name
}
}
|} in
test_query Test_schema.schema query (`Assoc [
"data", `Assoc [
"role_type", `Assoc [
"name", `String "role"
];
"user_type", `Assoc [
"name", `String "user"
];
]
])
);
]
2 changes: 1 addition & 1 deletion graphql/test/test_common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ let yojson = (module struct
Format.pp_print_text formatter (Yojson.Basic.pretty_to_string t)

let equal = (=)
end : Alcotest.TESTABLE with type t = Yojson.Basic.json)
end : Alcotest.TESTABLE with type t = Yojson.Basic.json) [@@warning "-3"]

let list_of_seq seq =
let rec loop seq =
Expand Down