Class: Tina4::GraphQL

Inherits:
Object
  • Object
show all
Defined in:
lib/tina4/graphql.rb

Overview

─── Main GraphQL class ──────────────────────────────────────────────

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(schema = nil) ⇒ GraphQL

Returns a new instance of GraphQL.



755
756
757
758
# File 'lib/tina4/graphql.rb', line 755

def initialize(schema = nil)
  @schema = schema || GraphQLSchema.new
  @executor = GraphQLExecutor.new(@schema)
end

Instance Attribute Details

#schemaObject (readonly)

Returns the value of attribute schema.



753
754
755
# File 'lib/tina4/graphql.rb', line 753

def schema
  @schema
end

Instance Method Details

#execute(query, variables: {}, context: {}, operation_name: nil) ⇒ Object

Execute a query string directly



761
762
763
764
765
766
767
768
769
# File 'lib/tina4/graphql.rb', line 761

def execute(query, variables: {}, context: {}, operation_name: nil)
  parser = GraphQLParser.new(query)
  document = parser.parse
  @executor.execute(document, variables: variables, context: context, operation_name: operation_name)
rescue GraphQLError => e
  { "data" => nil, "errors" => [{ "message" => e.message }] }
rescue => e
  { "data" => nil, "errors" => [{ "message" => "Internal error: #{e.message}" }] }
end

#handle_request(body, context: {}) ⇒ Object

Handle an HTTP request body (JSON string)



808
809
810
811
812
813
814
815
816
817
# File 'lib/tina4/graphql.rb', line 808

def handle_request(body, context: {})
  payload = JSON.parse(body)
  query = payload["query"] || ""
  variables = payload["variables"] || {}
  op_name = payload["operationName"]

  execute(query, variables: variables, context: context, operation_name: op_name)
rescue JSON::ParserError
  { "data" => nil, "errors" => [{ "message" => "Invalid JSON in request body" }] }
end

#introspectObject

Return schema metadata for debugging.



801
802
803
804
805
# File 'lib/tina4/graphql.rb', line 801

def introspect
  queries = @schema.queries.transform_values { |v| { type: v[:type], args: v[:args] || {} } }
  mutations = @schema.mutations.transform_values { |v| { type: v[:type], args: v[:args] || {} } }
  { types: @schema.types.keys, queries: queries, mutations: mutations }
end

#register_route(path = "/graphql") ⇒ Object

── Route Registration ─────────────────────────────────────────────Register a POST /graphql route in the Tina4 router.

gql = Tina4::GraphQL.new(schema)
gql.register_route           # POST /graphql
gql.register_route("/api/graphql")  # custom path


826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
# File 'lib/tina4/graphql.rb', line 826

def register_route(path = "/graphql")
  graphql = self
  Tina4.post path, auth: false do |request, response|
    body = request.body
    result = graphql.handle_request(body, context: { request: request })
    response.json(result)
  end

  # Optional: GET for GraphiQL/introspection
  Tina4.get path, auth: false do |request, response|
    query = request.params["query"]
    if query
      variables = request.params["variables"]
      variables = JSON.parse(variables) if variables.is_a?(String) && !variables.empty?
      result = graphql.execute(query, variables: variables || {}, context: { request: request })
      response.json(result)
    else
      response.html(graphiql_html(path))
    end
  end
end

#schema_sdlObject

Return schema as GraphQL SDL string.



772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
# File 'lib/tina4/graphql.rb', line 772

def schema_sdl
  sdl = ""
  @schema.types.each do |name, type_obj|
    sdl += "type #{name} {\n"
    type_obj.fields.each { |f| sdl += "  #{f[:name]}: #{f[:type]}\n" }
    sdl += "}\n\n"
  end
  unless @schema.queries.empty?
    sdl += "type Query {\n"
    @schema.queries.each do |name, config|
      args = (config[:args] || {}).map { |k, v| "#{k}: #{v}" }.join(", ")
      arg_str = args.empty? ? "" : "(#{args})"
      sdl += "  #{name}#{arg_str}: #{config[:type]}\n"
    end
    sdl += "}\n\n"
  end
  unless @schema.mutations.empty?
    sdl += "type Mutation {\n"
    @schema.mutations.each do |name, config|
      args = (config[:args] || {}).map { |k, v| "#{k}: #{v}" }.join(", ")
      arg_str = args.empty? ? "" : "(#{args})"
      sdl += "  #{name}#{arg_str}: #{config[:type]}\n"
    end
    sdl += "}\n\n"
  end
  sdl
end