graphql 0.18.1 → 0.18.2

Sign up to get free protection for your applications and to get access to all the features.
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