lib/graphql/schema/build_from_definition.rb in graphql-1.9.21 vs lib/graphql/schema/build_from_definition.rb in graphql-1.10.0.pre1

- old
+ new

@@ -46,19 +46,19 @@ case definition when GraphQL::Language::Nodes::SchemaDefinition raise InvalidDocumentError.new('Must provide only one schema definition.') if schema_definition schema_definition = definition when GraphQL::Language::Nodes::EnumTypeDefinition - types[definition.name] = build_enum_type(definition, type_resolver) + types[definition.name] = build_enum_type(definition, type_resolver).graphql_definition when GraphQL::Language::Nodes::ObjectTypeDefinition - types[definition.name] = build_object_type(definition, type_resolver, default_resolve: default_resolve) + types[definition.name] = build_object_type(definition, type_resolver, default_resolve: default_resolve).graphql_definition when GraphQL::Language::Nodes::InterfaceTypeDefinition - types[definition.name] = build_interface_type(definition, type_resolver) + types[definition.name] = build_interface_type(definition, type_resolver).graphql_definition when GraphQL::Language::Nodes::UnionTypeDefinition - types[definition.name] = build_union_type(definition, type_resolver) + types[definition.name] = build_union_type(definition, type_resolver).graphql_definition when GraphQL::Language::Nodes::ScalarTypeDefinition - types[definition.name] = build_scalar_type(definition, type_resolver, default_resolve: default_resolve) + types[definition.name] = build_scalar_type(definition, type_resolver, default_resolve: default_resolve).graphql_definition when GraphQL::Language::Nodes::InputObjectTypeDefinition types[definition.name] = build_input_object_type(definition, type_resolver) when GraphQL::Language::Nodes::DirectiveDefinition directives[definition.name] = build_directive(definition, type_resolver) end @@ -87,58 +87,55 @@ subscription_root_type = types['Subscription'] end raise InvalidDocumentError.new('Must provide schema definition with query type or a type named Query.') unless query_root_type - schema = Schema.define do - raise_definition_error true - + Class.new(GraphQL::Schema) do query query_root_type mutation mutation_root_type subscription subscription_root_type orphan_types types.values if default_resolve.respond_to?(:resolve_type) - resolve_type(default_resolve.method(:resolve_type)) + define_singleton_method(:resolve_type) do |*args| + default_resolve.resolve_type(*args) + end else - resolve_type(NullResolveType) + define_singleton_method(:resolve_type) do |*args| + NullResolveType.call(*args) + end end directives directives.values - end - schema.ast_node = schema_definition if schema_definition + if schema_definition + ast_node(schema_definition) + end - schema + # Load caches, check for errors + graphql_definition + end end NullResolveType = ->(type, obj, ctx) { - raise(GraphQL::RequiredImplementationMissingError, "Generated Schema cannot use Interface or Union types for execution. Implement resolve_type on your resolver.") + raise(NotImplementedError, "Generated Schema cannot use Interface or Union types for execution. Implement resolve_type on your resolver.") } - NullScalarCoerce = ->(val, _ctx) { val } - def build_enum_type(enum_type_definition, type_resolver) - enum = GraphQL::EnumType.define( - name: enum_type_definition.name, - description: enum_type_definition.description, - values: enum_type_definition.values.map do |enum_value_definition| - value = EnumType::EnumValue.define( - name: enum_value_definition.name, + builder = self + Class.new(GraphQL::Schema::Enum) do + graphql_name(enum_type_definition.name) + description(enum_type_definition.description) + ast_node(enum_type_definition) + enum_type_definition.values.each do |enum_value_definition| + value(enum_value_definition.name, value: enum_value_definition.name, - deprecation_reason: build_deprecation_reason(enum_value_definition.directives), + deprecation_reason: builder.build_deprecation_reason(enum_value_definition.directives), description: enum_value_definition.description, + ast_node: enum_value_definition, ) - - value.ast_node = enum_value_definition - - value end - ) - - enum.ast_node = enum_type_definition - - enum + end end def build_deprecation_reason(directives) deprecated_directive = directives.find{ |d| d.name == 'deprecated' } return unless deprecated_directive @@ -148,67 +145,63 @@ reason.value end def build_scalar_type(scalar_type_definition, type_resolver, default_resolve:) - scalar_type = GraphQL::ScalarType.define( - name: scalar_type_definition.name, - description: scalar_type_definition.description, - coerce: NullScalarCoerce, - ) + Class.new(GraphQL::Schema::Scalar) do + graphql_name(scalar_type_definition.name) + description(scalar_type_definition.description) + ast_node(scalar_type_definition) - scalar_type.ast_node = scalar_type_definition + if default_resolve.respond_to?(:coerce_input) + define_singleton_method(:coerce_input) do |val, ctx| + default_resolve.coerce_input(self, val, ctx) + end - if default_resolve.respond_to?(:coerce_input) - scalar_type = scalar_type.redefine( - coerce_input: ->(val, ctx) { default_resolve.coerce_input(scalar_type, val, ctx) }, - coerce_result: ->(val, ctx) { default_resolve.coerce_result(scalar_type, val, ctx) }, - ) + define_singleton_method(:coerce_result) do |val, ctx| + default_resolve.coerce_result(self, val, ctx) + end + end end - - scalar_type end def build_union_type(union_type_definition, type_resolver) - union = GraphQL::UnionType.define( - name: union_type_definition.name, - description: union_type_definition.description, - possible_types: union_type_definition.types.map{ |type_name| type_resolver.call(type_name) }, - ) - - union.ast_node = union_type_definition - - union + Class.new(GraphQL::Schema::Union) do + graphql_name(union_type_definition.name) + description(union_type_definition.description) + possible_types(*union_type_definition.types.map { |type_name| type_resolver.call(type_name) }) + ast_node(union_type_definition) + end end def build_object_type(object_type_definition, type_resolver, default_resolve:) + builder = self type_def = nil - typed_resolve_fn = ->(field, obj, args, ctx) { default_resolve.call(type_def, field, obj, args, ctx) } - defns = { - name: object_type_definition.name, - description: object_type_definition.description, - interfaces: object_type_definition.interfaces.map{ |interface_name| type_resolver.call(interface_name) }, - } - obj_fields = Hash[build_fields(object_type_definition.fields, type_resolver, default_resolve: typed_resolve_fn)] - if obj_fields.any? - defns[:fields] = obj_fields + typed_resolve_fn = ->(field, obj, args, ctx) { default_resolve.call(type_def.graphql_definition, field, obj, args, ctx) } + Class.new(GraphQL::Schema::Object) do + type_def = self + graphql_name(object_type_definition.name) + description(object_type_definition.description) + ast_node(object_type_definition) + + object_type_definition.interfaces.each do |interface_name| + interface_defn = type_resolver.call(interface_name) + implements(interface_defn) + end + + builder.build_fields(self, object_type_definition.fields, type_resolver, default_resolve: typed_resolve_fn) end - type_def = GraphQL::ObjectType.define(**defns) - type_def.ast_node = object_type_definition - type_def end def build_input_object_type(input_object_type_definition, type_resolver) - input = GraphQL::InputObjectType.define( - name: input_object_type_definition.name, - description: input_object_type_definition.description, - arguments: Hash[build_input_arguments(input_object_type_definition, type_resolver)], - ) - - input.ast_node = input_object_type_definition - - input + builder = self + Class.new(GraphQL::Schema::InputObject) do + graphql_name(input_object_type_definition.name) + description(input_object_type_definition.description) + ast_node(input_object_type_definition) + builder.build_arguments(self, input_object_type_definition.fields, type_resolver) + end end def build_default_value(default_value) case default_value when GraphQL::Language::Nodes::Enum @@ -222,133 +215,74 @@ else default_value end end - def build_input_arguments(input_object_type_definition, type_resolver) - input_object_type_definition.fields.map do |input_argument| - kwargs = {} + def build_arguments(type_class, arguments, type_resolver) + builder = self - if !input_argument.default_value.nil? - kwargs[:default_value] = build_default_value(input_argument.default_value) + arguments.each do |argument_defn| + default_value_kwargs = {} + if !argument_defn.default_value.nil? + default_value_kwargs[:default_value] = builder.build_default_value(argument_defn.default_value) end - argument = GraphQL::Argument.define( - name: input_argument.name, - type: type_resolver.call(input_argument.type), - description: input_argument.description, + type_class.argument( + argument_defn.name, + type: type_resolver.call(argument_defn.type), + required: false, + description: argument_defn.description, + ast_node: argument_defn, + camelize: false, method_access: false, - **kwargs, + **default_value_kwargs ) - - argument.ast_node = input_argument - - [ - input_argument.name, - argument - ] end end def build_directive(directive_definition, type_resolver) - directive_args = Hash[build_directive_arguments(directive_definition, type_resolver)] - - defn = { - name: directive_definition.name, - description: directive_definition.description, - locations: directive_definition.locations.map { |location| location.name.to_sym }, - } - - if directive_args.any? - defn[:arguments] = directive_args + builder = self + Class.new(GraphQL::Schema::Directive) do + graphql_name(directive_definition.name) + description(directive_definition.description) + locations(*directive_definition.locations.map { |location| location.name.to_sym }) + ast_node(directive_definition) + builder.build_arguments(self, directive_definition.arguments, type_resolver) end - - directive = GraphQL::Directive.define(**defn) - directive.ast_node = directive_definition - - directive end - def build_directive_arguments(directive_definition, type_resolver) - directive_definition.arguments.map do |directive_argument| - kwargs = {} + def build_interface_type(interface_type_definition, type_resolver) + builder = self + Module.new do + include GraphQL::Schema::Interface + graphql_name(interface_type_definition.name) + description(interface_type_definition.description) + ast_node(interface_type_definition) - if !directive_argument.default_value.nil? - kwargs[:default_value] = build_default_value(directive_argument.default_value) - end - - argument = GraphQL::Argument.define( - name: directive_argument.name, - type: type_resolver.call(directive_argument.type), - description: directive_argument.description, - method_access: false, - **kwargs, - ) - - argument.ast_node = directive_argument - - [ - directive_argument.name, - argument - ] + builder.build_fields(self, interface_type_definition.fields, type_resolver, default_resolve: nil) end end - def build_interface_type(interface_type_definition, type_resolver) - interface = GraphQL::InterfaceType.define( - name: interface_type_definition.name, - description: interface_type_definition.description, - fields: Hash[build_fields(interface_type_definition.fields, type_resolver, default_resolve: nil)], - ) + def build_fields(owner, field_definitions, type_resolver, default_resolve:) + builder = self - interface.ast_node = interface_type_definition - - interface - end - - def build_fields(field_definitions, type_resolver, default_resolve:) field_definitions.map do |field_definition| - field_arguments = Hash[field_definition.arguments.map do |argument| - kwargs = {} + type_name = resolve_type_name(field_definition.type) - if !argument.default_value.nil? - kwargs[:default_value] = build_default_value(argument.default_value) - end - - arg = GraphQL::Argument.define( - name: argument.name, - description: argument.description, - type: type_resolver.call(argument.type), - method_access: false, - **kwargs, - ) - - arg.ast_node = argument - - [argument.name, arg] - end] - - field = nil - - defns = { - name: field_definition.name, + field = owner.field( + field_definition.name, description: field_definition.description, type: type_resolver.call(field_definition.type), - resolve: ->(obj, args, ctx) { default_resolve.call(field, obj, args, ctx) }, + null: true, + connection: type_name.end_with?("Connection"), + resolve: ->(obj, args, ctx) { default_resolve.call(field.graphql_definition, obj, args, ctx) }, deprecation_reason: build_deprecation_reason(field_definition.directives), - } - - if field_arguments.any? - defns[:arguments] = field_arguments + ast_node: field_definition, + method_conflict_warning: false, + camelize: false, + ) do + builder.build_arguments(self, field_definition.arguments, type_resolver) end - - field = GraphQL::Field.define(**defns) - - field.ast_node = field_definition - - type_name = resolve_type_name(field_definition.type) - field.connection = type_name.end_with?("Connection") - [field_definition.name, field] end end def resolve_type(types, ast_node) type = GraphQL::Schema::TypeExpression.build_type(types, ast_node)