graphql 0.18.1 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4320e19052975ac0ba38fac054d7d56d044657e1
4
- data.tar.gz: 2045f552c2acd454a57f4c0ec80f9547f7c6b875
3
+ metadata.gz: c25c28ed78a94aead6ff0547d559c15b3c00c01f
4
+ data.tar.gz: 81c73c51e31e934391e9da8daa3d6915acaccb67
5
5
  SHA512:
6
- metadata.gz: 0db74452c453b954039a685aaa25ad875325de13c0f7eb152dd4ff09a139048b73c83ce637cc84b7824ffb4311ce1de0041b671444a4a208131bb49ed71c6dc9
7
- data.tar.gz: bf2b4faf5545b8d13ee5ab3b370e9ea4ab4954e40f458a87b2551bf666e97e4d27270b618b2644b1cdc56f48d7681b48edf3ac74171ce9cc37d113a6bff5d7d6
6
+ metadata.gz: 3189f4d3b79efdf1082168bcf338159f6a89f04ba0c51d78ca35e64a1284438b08b3424d181db23d8e01c3505fa83cb8c915dc9d8a419cb1d91dbe0af0166d06
7
+ data.tar.gz: f1a2c37b55214c42258b3f708d15a1dbe33d5bb0e01a8333d0818e494a96319f92d7e942c6efb71591596eafbd9c8e6f108042b928ea1c5631c295c483f86886
@@ -70,3 +70,4 @@ require "graphql/internal_representation"
70
70
  require "graphql/static_validation"
71
71
  require "graphql/version"
72
72
  require "graphql/relay"
73
+ require "graphql/execution"
@@ -32,11 +32,11 @@ module GraphQL
32
32
  memo[:complexities_on_type].push(TypeComplexity.new)
33
33
  else
34
34
  type_complexities = memo[:complexities_on_type].pop
35
- own_complexity = if GraphQL::Query::DirectiveResolution.include_node?(irep_node, memo[:query])
35
+ own_complexity = if GraphQL::Execution::DirectiveChecks.skip?(irep_node, memo[:query])
36
+ 0
37
+ else
36
38
  child_complexity = type_complexities.max_possible_complexity
37
39
  get_complexity(irep_node, memo[:query], child_complexity)
38
- else
39
- 0
40
40
  end
41
41
  memo[:complexities_on_type].last.merge(irep_node.definitions, own_complexity)
42
42
  end
@@ -29,13 +29,13 @@ module GraphQL
29
29
  memo[:skip_current_scope] = true
30
30
  elsif memo[:skip_current_scope]
31
31
  # we're inside an introspection query
32
- elsif GraphQL::Query::DirectiveResolution.include_node?(irep_node, memo[:query])
32
+ elsif GraphQL::Execution::DirectiveChecks.include?(irep_node, memo[:query])
33
33
  memo[:current_depth] += 1
34
34
  end
35
35
  else
36
36
  if GraphQL::Schema::DYNAMIC_FIELDS.include?(irep_node.definition_name)
37
37
  memo[:skip_current_scope] = false
38
- elsif GraphQL::Query::DirectiveResolution.include_node?(irep_node, memo[:query])
38
+ elsif GraphQL::Execution::DirectiveChecks.include?(irep_node, memo[:query])
39
39
  if memo[:max_depth] < memo[:current_depth]
40
40
  memo[:max_depth] = memo[:current_depth]
41
41
  end
@@ -0,0 +1,2 @@
1
+ require "graphql/execution/directive_checks"
2
+ require "graphql/execution/typecast"
@@ -0,0 +1,32 @@
1
+ module GraphQL
2
+ module Execution
3
+ # Boolean checks for how an AST node's directives should
4
+ # influence its execution
5
+ module DirectiveChecks
6
+ SKIP = "skip"
7
+ INCLUDE = "include"
8
+
9
+ module_function
10
+
11
+ # This covers `@include(if:)` & `@skip(if:)`
12
+ # @return [Boolean] Should this node be skipped altogether?
13
+ def skip?(irep_node, query)
14
+ irep_node.directives.each do |directive_node|
15
+ if directive_node.name == SKIP || directive_node.name == INCLUDE
16
+ directive_defn = directive_node.definitions.first
17
+ args = query.arguments_for(directive_node, directive_defn)
18
+ if !directive_defn.include?(args)
19
+ return true
20
+ end
21
+ end
22
+ end
23
+ false
24
+ end
25
+
26
+ # @return [Boolean] Should this node be included in the query?
27
+ def include?(irep_node, query)
28
+ !skip?(irep_node, query)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module GraphQL
2
+ module Execution
3
+ # GraphQL object `{value, type}` can be cast to `other_type` when:
4
+ # - `type == other_type`
5
+ # - `type` is a union and it resolves `value` to `other_type`
6
+ # - `other_type` is a union and `type` is a member
7
+ # - `type` is an interface and it resolves `value` to `other_type`
8
+ # - `other_type` is an interface and `type` implements that interface
9
+ module Typecast
10
+ # While `value` is exposed by GraphQL as an instance of `current_type`,
11
+ # should it _also_ be treated as an instance of `potential_type`?
12
+ #
13
+ # This is used for checking whether fragments apply to an object.
14
+ #
15
+ # @return [Boolean] Can `value` be evaluated as a `potential_type`?
16
+ def self.compatible?(value, current_type, potential_type, query_ctx)
17
+ if potential_type == current_type
18
+ true
19
+ elsif current_type.kind.union?
20
+ current_type.resolve_type(value, query_ctx) == potential_type
21
+ elsif potential_type.kind.union?
22
+ potential_type.include?(current_type)
23
+ elsif current_type.kind.interface?
24
+ current_type.resolve_type(value, query_ctx) == potential_type
25
+ elsif potential_type.kind.interface?
26
+ current_type.interfaces.include?(potential_type)
27
+ else
28
+ false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,12 @@
1
+ require "graphql/query/arguments"
2
+ require "graphql/query/context"
3
+ require "graphql/query/executor"
4
+ require "graphql/query/literal_input"
5
+ require "graphql/query/serial_execution"
6
+ require "graphql/query/variables"
7
+ require "graphql/query/input_validation_result"
8
+ require "graphql/query/variable_validation_error"
9
+
1
10
  module GraphQL
2
11
  # A combination of query string and {Schema} instance which can be reduced to a {#result}.
3
12
  class Query
@@ -164,14 +173,3 @@ module GraphQL
164
173
  end
165
174
  end
166
175
  end
167
-
168
- require "graphql/query/arguments"
169
- require "graphql/query/context"
170
- require "graphql/query/directive_resolution"
171
- require "graphql/query/executor"
172
- require "graphql/query/literal_input"
173
- require "graphql/query/serial_execution"
174
- require "graphql/query/type_resolver"
175
- require "graphql/query/variables"
176
- require "graphql/query/input_validation_result"
177
- require "graphql/query/variable_validation_error"
@@ -1,3 +1,9 @@
1
+ require "graphql/query/serial_execution/execution_context"
2
+ require "graphql/query/serial_execution/value_resolution"
3
+ require "graphql/query/serial_execution/field_resolution"
4
+ require "graphql/query/serial_execution/operation_resolution"
5
+ require "graphql/query/serial_execution/selection_resolution"
6
+
1
7
  module GraphQL
2
8
  class Query
3
9
  class SerialExecution
@@ -33,9 +39,3 @@ module GraphQL
33
39
  end
34
40
  end
35
41
  end
36
-
37
- require "graphql/query/serial_execution/execution_context"
38
- require "graphql/query/serial_execution/value_resolution"
39
- require "graphql/query/serial_execution/field_resolution"
40
- require "graphql/query/serial_execution/operation_resolution"
41
- require "graphql/query/serial_execution/selection_resolution"
@@ -13,7 +13,7 @@ module GraphQL
13
13
 
14
14
  def result
15
15
  irep_node.children.each_with_object({}) do |(name, irep_node), memo|
16
- if included_by_directives?(irep_node, execution_context.query) && applies_to_type?(irep_node, type, target)
16
+ if GraphQL::Execution::DirectiveChecks.include?(irep_node, execution_context.query) && applies_to_type?(irep_node, type, target)
17
17
  field_result = execution_context.strategy.field_resolution.new(
18
18
  irep_node,
19
19
  type,
@@ -27,13 +27,9 @@ module GraphQL
27
27
 
28
28
  private
29
29
 
30
- def included_by_directives?(irep_node, query)
31
- GraphQL::Query::DirectiveResolution.include_node?(irep_node, query)
32
- end
33
-
34
30
  def applies_to_type?(irep_node, type, target)
35
31
  irep_node.definitions.any? { |child_type, field_defn|
36
- GraphQL::Query::TypeResolver.new(target, child_type, type, execution_context.query.context).type
32
+ GraphQL::Execution::Typecast.compatible?(target, child_type, type, execution_context.query.context)
37
33
  }
38
34
  end
39
35
  end
@@ -53,17 +53,19 @@ module GraphQL
53
53
  deprecate(:connection_for_items, :connection_for_nodes, 2016, 9)
54
54
  end
55
55
 
56
- attr_reader :nodes, :arguments, :max_page_size, :parent
56
+ attr_reader :nodes, :arguments, :max_page_size, :parent, :field
57
57
 
58
58
  # Make a connection, wrapping `nodes`
59
59
  # @param [Object] The collection of nodes
60
60
  # @param Query arguments
61
+ # @param field [Object] The underlying field
61
62
  # @param max_page_size [Int] The maximum number of results to return
62
63
  # @param parent [Object] The object which this collection belongs to
63
- def initialize(nodes, arguments, max_page_size: nil, parent: nil)
64
+ def initialize(nodes, arguments, field:, max_page_size: nil, parent: nil)
64
65
  @nodes = nodes
65
66
  @arguments = arguments
66
67
  @max_page_size = max_page_size
68
+ @field = field
67
69
  @parent = parent
68
70
  end
69
71
 
@@ -33,7 +33,7 @@ module GraphQL
33
33
  def self.create(underlying_field, max_page_size: nil)
34
34
  underlying_field.arguments = DEFAULT_ARGUMENTS.merge(underlying_field.arguments)
35
35
  original_resolve = underlying_field.resolve_proc
36
- underlying_field.resolve = GraphQL::Relay::ConnectionResolve.new(underlying_field.name, original_resolve, max_page_size: max_page_size)
36
+ underlying_field.resolve = GraphQL::Relay::ConnectionResolve.new(underlying_field, original_resolve, max_page_size: max_page_size)
37
37
  underlying_field
38
38
  end
39
39
  end
@@ -1,8 +1,8 @@
1
1
  module GraphQL
2
2
  module Relay
3
3
  class ConnectionResolve
4
- def initialize(field_name, underlying_resolve, max_page_size: nil)
5
- @field_name = field_name
4
+ def initialize(field, underlying_resolve, max_page_size: nil)
5
+ @field = field
6
6
  @underlying_resolve = underlying_resolve
7
7
  @max_page_size = max_page_size
8
8
  end
@@ -10,7 +10,7 @@ module GraphQL
10
10
  def call(obj, args, ctx)
11
11
  nodes = @underlying_resolve.call(obj, args, ctx)
12
12
  connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(nodes)
13
- connection_class.new(nodes, args, max_page_size: @max_page_size, parent: obj)
13
+ connection_class.new(nodes, args, field: @field, max_page_size: @max_page_size, parent: obj)
14
14
  end
15
15
  end
16
16
  end
@@ -0,0 +1,75 @@
1
+ module GraphQL
2
+ class Schema
3
+ # - query_initialize
4
+ # - query_finalize
5
+ # - field_resolve
6
+ #
7
+ # @example Closing a socket when the query is finished
8
+ # SocketClosingMiddleware = GraphQL::Schema::Middleware.define do
9
+ # finalize_query -> (memo, env) {
10
+ # query.context[:socket].close
11
+ # }
12
+ # end
13
+ #
14
+ # @example Timing a query
15
+ # QueryTimerMiddleware = GraphQL::Schema::Middleware.define do
16
+ # initialize_query -> (env) {
17
+ # env.merge!({
18
+ # query_start_time: Time.now,
19
+ # field_times: [],
20
+ # })
21
+ # }
22
+ #
23
+ # resolve_field -> (env) {
24
+ # field_time = {
25
+ # start_time: Time.now,
26
+ # own_elapsed: nil,
27
+ # child_elapsed: 0,
28
+ # }
29
+ #
30
+ # memo[:field_times] << field_time
31
+ # memo
32
+ # }
33
+ #
34
+ # after_field { |memo, env|
35
+ # field_time = memo[:field_times].pop
36
+ # total_elapsed = Time.now - field_time[:start_time]
37
+ # own_elapsed = total_elapsed - field_time[:child_elapsed]
38
+ #
39
+ # field_name = "#{env[:parent_type].name}.#{env[:field_definition].name}(#{env[:arguments].to_h.to_json})"
40
+ # Logger.info("[GraphQL Field] #{field_name} #{own_elapsed}")
41
+ #
42
+ # parent_field_time = memo[:field_times].last
43
+ # if parent_field_time
44
+ # parent_field_time[:child_elapsed] += total_elapsed
45
+ # end
46
+ # }
47
+ #
48
+ # after_query { |memo, env|
49
+ # elapsed = Time.now - memo[:query_start_time]
50
+ # Logger.info("[GraphQL Elapsed] #{elapsed}")
51
+ # }
52
+ # end
53
+ class Middleware
54
+ EVENTS = [:before_query, :after_query, :before_field, :after_field]
55
+ class << self
56
+ attr_reader :handlers
57
+ def handlers
58
+ @handlers ||= {}
59
+ end
60
+
61
+ def on(event_name, &handler)
62
+ if EVENTS.include?(event_name)
63
+ handlers[event_name] = handler
64
+ else
65
+ raise("Can't attach handler to #{event_name} (must be one of: #{EVENTS})")
66
+ end
67
+ end
68
+ end
69
+
70
+ def trigger(event_name, *args)
71
+ self.class.handlers[event_name].call(*args)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -15,6 +15,9 @@ module GraphQL
15
15
  def validate_directive(ast_directive, directive_names, context)
16
16
  if !directive_names.include?(ast_directive.name)
17
17
  context.errors << message("Directive @#{ast_directive.name} is not defined", ast_directive, context: context)
18
+ GraphQL::Language::Visitor::SKIP
19
+ else
20
+ nil
18
21
  end
19
22
  end
20
23
  end
@@ -1,3 +1,3 @@
1
1
  module GraphQL
2
- VERSION = "0.18.1"
2
+ VERSION = "0.18.2"
3
3
  end
@@ -8,6 +8,7 @@ describe GraphQL::Relay::ConnectionType do
8
8
  rebels {
9
9
  basesWithCustomEdge {
10
10
  totalCountTimes100
11
+ fieldName
11
12
  edges {
12
13
  upcasedName
13
14
  upcasedParentName
@@ -26,6 +27,7 @@ describe GraphQL::Relay::ConnectionType do
26
27
  result = query(query_string)
27
28
  bases = result["data"]["rebels"]["basesWithCustomEdge"]
28
29
  assert_equal 300, bases["totalCountTimes100"]
30
+ assert_equal 'basesWithCustomEdge', bases["fieldName"]
29
31
  assert_equal ["YAVIN", "ECHO BASE", "SECRET HIDEOUT"] , bases["edges"].map { |e| e["upcasedName"] }
30
32
  assert_equal ["Yavin", "Echo Base", "Secret Hideout"] , bases["edges"].map { |e| e["node"]["name"] }
31
33
  assert_equal ["CustomBaseEdge"] , bases["edges"].map { |e| e["edgeClassName"] }.uniq
@@ -77,6 +77,8 @@ CustomEdgeBaseConnectionType = BaseType.define_connection(edge_class: CustomBase
77
77
  type types.Int
78
78
  resolve -> (obj, args, ctx) { obj.nodes.count * 100 }
79
79
  end
80
+
81
+ field :fieldName, types.String, resolve: -> (obj, args, ctx) { obj.field.name }
80
82
  end
81
83
 
82
84
  Faction = GraphQL::ObjectType.define do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.1
4
+ version: 0.18.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-07 00:00:00.000000000 Z
11
+ date: 2016-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: codeclimate-test-reporter
@@ -268,6 +268,9 @@ files:
268
268
  - lib/graphql/directive/include_directive.rb
269
269
  - lib/graphql/directive/skip_directive.rb
270
270
  - lib/graphql/enum_type.rb
271
+ - lib/graphql/execution.rb
272
+ - lib/graphql/execution/directive_checks.rb
273
+ - lib/graphql/execution/typecast.rb
271
274
  - lib/graphql/execution_error.rb
272
275
  - lib/graphql/field.rb
273
276
  - lib/graphql/field/resolve.rb
@@ -315,7 +318,6 @@ files:
315
318
  - lib/graphql/query.rb
316
319
  - lib/graphql/query/arguments.rb
317
320
  - lib/graphql/query/context.rb
318
- - lib/graphql/query/directive_resolution.rb
319
321
  - lib/graphql/query/executor.rb
320
322
  - lib/graphql/query/input_validation_result.rb
321
323
  - lib/graphql/query/literal_input.rb
@@ -325,7 +327,6 @@ files:
325
327
  - lib/graphql/query/serial_execution/operation_resolution.rb
326
328
  - lib/graphql/query/serial_execution/selection_resolution.rb
327
329
  - lib/graphql/query/serial_execution/value_resolution.rb
328
- - lib/graphql/query/type_resolver.rb
329
330
  - lib/graphql/query/variable_validation_error.rb
330
331
  - lib/graphql/query/variables.rb
331
332
  - lib/graphql/relay.rb
@@ -345,6 +346,7 @@ files:
345
346
  - lib/graphql/schema.rb
346
347
  - lib/graphql/schema/catchall_middleware.rb
347
348
  - lib/graphql/schema/invalid_type_error.rb
349
+ - lib/graphql/schema/middleware.rb
348
350
  - lib/graphql/schema/middleware_chain.rb
349
351
  - lib/graphql/schema/possible_types.rb
350
352
  - lib/graphql/schema/printer.rb
@@ -419,7 +421,6 @@ files:
419
421
  - spec/graphql/query/executor_spec.rb
420
422
  - spec/graphql/query/serial_execution/execution_context_spec.rb
421
423
  - spec/graphql/query/serial_execution/value_resolution_spec.rb
422
- - spec/graphql/query/type_resolver_spec.rb
423
424
  - spec/graphql/query/variables_spec.rb
424
425
  - spec/graphql/query_spec.rb
425
426
  - spec/graphql/relay/array_connection_spec.rb
@@ -525,7 +526,6 @@ test_files:
525
526
  - spec/graphql/query/executor_spec.rb
526
527
  - spec/graphql/query/serial_execution/execution_context_spec.rb
527
528
  - spec/graphql/query/serial_execution/value_resolution_spec.rb
528
- - spec/graphql/query/type_resolver_spec.rb
529
529
  - spec/graphql/query/variables_spec.rb
530
530
  - spec/graphql/query_spec.rb
531
531
  - spec/graphql/relay/array_connection_spec.rb
@@ -1,16 +0,0 @@
1
- module GraphQL
2
- class Query
3
- module DirectiveResolution
4
- def self.include_node?(irep_node, query)
5
- irep_node.directives.each do |directive_node|
6
- directive_defn = directive_node.definitions.first
7
- args = query.arguments_for(directive_node, directive_defn)
8
- if !directive_defn.include?(args)
9
- return false
10
- end
11
- end
12
- true
13
- end
14
- end
15
- end
16
- end
@@ -1,25 +0,0 @@
1
- module GraphQL
2
- class Query
3
- # Given an object, a type name (from the query) and a type object,
4
- # Return the type that should be used for `object`
5
- # or Return `nil` if it's a mismatch
6
- class TypeResolver
7
- attr_reader :type
8
- def initialize(target, child_type, parent_type, query_ctx)
9
- @type = if child_type.nil?
10
- nil
11
- elsif parent_type.kind.union?
12
- parent_type.resolve_type(target)
13
- elsif child_type.kind.union? && child_type.include?(parent_type)
14
- parent_type
15
- elsif child_type.kind.interface?
16
- child_type.resolve_type(target, query_ctx)
17
- elsif child_type == parent_type
18
- parent_type
19
- else
20
- nil
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,8 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe GraphQL::Query::TypeResolver do
4
- it "resolves correcty when child_type is UnionType" do
5
- type = GraphQL::Query::TypeResolver.new(MILKS[1], DairyProductUnion, MilkType, nil).type
6
- assert_equal(MilkType, type)
7
- end
8
- end