graphql-decorate 0.1.1 → 0.2.1

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
  SHA256:
3
- metadata.gz: eebb3163d3b156e31469281fed745c5512628d8d53bac95d14a482d5973eba3f
4
- data.tar.gz: cf29b63e882f792f0b862b311b7dbc1f52b5be1d0685863afeeb0a11e7bb5dd6
3
+ metadata.gz: e23e910653e03c46982bf8916ab3f15cde1be96a6436cabbf0271c40a11f1b4d
4
+ data.tar.gz: d71940ac1feabb05b64228812ad1768f8f4f288e2ff105a619ee8cd02b00ce8a
5
5
  SHA512:
6
- metadata.gz: 1d14eee9d8590363f51582f8d199ea8f89b6f7af6d7391097839c43ac3573830b68eb81937b0e73645bfffc21caa2188ee187d979c2b25637872a171d504b0c9
7
- data.tar.gz: 3dd3cfeabf0b687aa4fc80e91779378b113b9b56145f6a172ca0930bc954511fba709266f62f552d257fd65b76d8b66b7bb1e6aaf211ef497ac2fbc8ce066e66
6
+ metadata.gz: 457e1cd6d2c62e5f463ccfacd8fa62f3e444c4b980d5e1d0b24b7b59aa960bcbf3c38cb0013055c793bafb3af86a5c0c2a68ae687b0c6af66de0b5b24b96d811
7
+ data.tar.gz: 678fb9bd85a0de6e6f0d336f2e812f91e1a326c7e3bff426159ff2bf2a83af5bc93bdf1b4ff490650f3a851f8d42b0370955d552bf57d22a47f183e8c2335462
data/README.md CHANGED
@@ -131,7 +131,8 @@ end
131
131
  ### Collections
132
132
  By default `graphql-decorate` recognizes `Array` and `ActiveRecord::Relation` object types and
133
133
  decorates every element in the collection. If you have other collection types that should have
134
- their elements decorated, you can add them in the configuration.
134
+ their elements decorated, you can add them in the configuration. Custom collection classes must
135
+ respond to `#map`.
135
136
  ```ruby
136
137
  GraphQL::Decorate.configure do |config|
137
138
  config.custom_collection_classes = [Mongoid::Relations::Targets::Enumerable]
@@ -7,10 +7,10 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "graphql-decorate"
8
8
  spec.version = GraphQL::Decorate::VERSION
9
9
  spec.authors = ["Ben Brook"]
10
- spec.email = ["bbrook@truecar.com"]
10
+ spec.email = ["bbrook154@gmail.com"]
11
11
 
12
12
  spec.summary = 'A decorator integration for the GraphQL gem'
13
- spec.homepage = 'https://git.corp.tc/bbrook/graphql-decorate'
13
+ spec.homepage = 'https://www.github.com/TrueCar/graphql-decorate'
14
14
  spec.license = "MIT"
15
15
 
16
16
  # Specify which files should be added to the gem when it is released.
@@ -4,10 +4,14 @@ require_relative 'decorate/configuration'
4
4
  require_relative 'decorate/object_integration'
5
5
  require_relative 'decorate/field_integration'
6
6
  require_relative 'decorate/field_extension'
7
- require_relative 'decorate/resolution'
7
+ require_relative 'decorate/object'
8
8
  require_relative 'decorate/type_attributes'
9
+ require_relative 'decorate/field_context'
10
+ require_relative 'decorate/connection'
9
11
 
12
+ # Matching the graphql-ruby namespace
10
13
  module GraphQL
14
+ # Entry point for graphql-decorate. Handles configuration.
11
15
  module Decorate
12
16
  # @return [Configuration] Returns a new instance of GraphQL::Decorate::Configuration.
13
17
  def self.configuration
@@ -1,5 +1,6 @@
1
1
  module GraphQL
2
2
  module Decorate
3
+ # Allows overriding default decoration and custom collection class behavior.
3
4
  class Configuration
4
5
  # @return [Proc] Proc that decorates a given object and context with a given decorator class.
5
6
  attr_reader :evaluate_decorator
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Decorate
4
+ # Wraps a GraphQL::Pagination::Connection object to decorate values after pagination is applied.
5
+ class Connection
6
+ # @return [GraphQL::Pagination::Connection] Connection being decorated
7
+ attr_reader :connection
8
+
9
+ # @return [GraphQL::Decorate::FieldContext] Current field context
10
+ attr_reader :field_context
11
+
12
+ def initialize(connection, field_context)
13
+ @connection = connection
14
+ @field_context = field_context
15
+ end
16
+
17
+ # @return [Array] Decorated nodes after pagination is applied
18
+ def nodes
19
+ nodes = @connection.nodes
20
+ nodes.map { |node| GraphQL::Decorate::Object.new(node, field_context).decorate }
21
+ end
22
+
23
+ # @see nodes
24
+ # @return [Array] Decorated nodes after pagination is applied
25
+ def edge_nodes
26
+ nodes
27
+ end
28
+
29
+ class << self
30
+ private
31
+
32
+ def method_missing(symbol, *args, &block)
33
+ @connection.class.send(symbol, *args, &block)
34
+ end
35
+
36
+ def respond_to_missing?(method, include_private = false)
37
+ @connection.class.respond_to_missing(method, include_private)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def method_missing(symbol, *args, &block)
44
+ @connection.send(symbol, *args, &block)
45
+ end
46
+
47
+ def respond_to_missing?(method, include_private = false)
48
+ @connection.respond_to_missing(method, include_private)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Decorate
4
+ # Wraps current GraphQL::Query::Context and options provided to a field for portability.
5
+ class FieldContext
6
+ # @return [GraphQL::Query::Context] Current GraphQL query context
7
+ attr_reader :context
8
+
9
+ # @return [Hash] Options provided to the field being decorated
10
+ attr_reader :options
11
+
12
+ def initialize(context, options)
13
+ @context = context
14
+ @options = options
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,19 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module Decorate
4
+ # Extension run after fields are resolved to decorate their value.
4
5
  class FieldExtension < GraphQL::Schema::FieldExtension
5
6
  # Extension to be called after lazy loading.
6
7
  # @param context [GraphQL::Query::Context] The current GraphQL query context.
7
8
  # @param value [Object, GraphQL::Schema::Object] The object being decorated. Can be a schema object if the field hasn't been resolved yet.
8
- # @return [Object] Decorated object.
9
+ # @return [::Object, GraphQL::Decorate::Connection] Decorated object.
9
10
  def after_resolve(context:, value:, **_rest)
10
11
  return if value.nil?
11
12
 
12
- collection = collection_classes.any? { |c| value.is_a?(c) }
13
- if collection
14
- value.map { |item| decorate(item, context) }
13
+ field_context = GraphQL::Decorate::FieldContext.new(context, options)
14
+ if value.is_a?(GraphQL::Pagination::Connection)
15
+ GraphQL::Decorate::Connection.new(value, field_context)
16
+ elsif collection_classes.any? { |c| value.is_a?(c) }
17
+ value.map { |item| decorate(item, field_context) }
15
18
  else
16
- decorate(value, context)
19
+ decorate(value, field_context)
17
20
  end
18
21
  end
19
22
 
@@ -25,8 +28,8 @@ module GraphQL
25
28
  klasses
26
29
  end
27
30
 
28
- def decorate(object, context)
29
- GraphQL::Decorate::Resolution.new(object, context, options).resolve
31
+ def decorate(object, field_context)
32
+ GraphQL::Decorate::Object.new(object, field_context).decorate
30
33
  end
31
34
  end
32
35
  end
@@ -1,5 +1,6 @@
1
1
  module GraphQL
2
2
  module Decorate
3
+ # Extends default field behavior and adds extension to the field if it should be decorated.
3
4
  module FieldIntegration
4
5
  # Overridden field initializer
5
6
  # @param type [GraphQL::Schema::Object] The type to add the extension to.
@@ -15,6 +16,8 @@ module GraphQL
15
16
 
16
17
  def get_extension_options(type)
17
18
  type_attributes = GraphQL::Decorate::TypeAttributes.new(type)
19
+ return unless type_attributes.decorator_class
20
+
18
21
  {
19
22
  decorator_class: type_attributes.decorator_class,
20
23
  decorator_evaluator: type_attributes.decorator_evaluator,
@@ -24,10 +27,11 @@ module GraphQL
24
27
  end
25
28
 
26
29
  def extend_with_decorator(options)
27
- ext = GraphQL::Decorate::FieldExtension.new(field: self, options: options)
28
- @extensions = @extensions.dup
29
- @extensions.unshift(ext)
30
- @extensions.freeze
30
+ extension(GraphQL::Decorate::FieldExtension, options)
31
+ # ext = GraphQL::Decorate::FieldExtension.new(field: self, options: options)
32
+ # @extensions = @extensions.dup
33
+ # @extensions.unshift(ext)
34
+ # @extensions.freeze
31
35
  end
32
36
  end
33
37
  end
@@ -1,20 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module Decorate
4
- class Resolution
5
- # @param object [Object] Object being resolved.
6
- # @param graphql_context [GraphQL::Query::Context] CurrentGraphQL query context.
7
- # @param extension_options [Hash] Options provided from the field extension.
8
- def initialize(object, graphql_context, extension_options)
4
+ # Handles decorating an object given its current field context.
5
+ class Object
6
+ # @param object [Object] Object being decorated.
7
+ # @param field_context [GraphQL::Decorate::FieldContext] Current GraphQL field context and options.
8
+ def initialize(object, field_context)
9
9
  @object = object
10
- @graphql_context = graphql_context
11
- @extension_options = extension_options
10
+ @field_context = field_context
12
11
  @default_decorator_context = { graphql: true }
13
12
  end
14
13
 
15
14
  # Resolve the object with decoration.
16
15
  # @return [Object] Decorated object if possible, otherwise the original object.
17
- def resolve
16
+ def decorate
18
17
  if decorator_class
19
18
  GraphQL::Decorate.configuration.evaluate_decorator.call(decorator_class, object, decorator_context)
20
19
  else
@@ -24,20 +23,20 @@ module GraphQL
24
23
 
25
24
  private
26
25
 
27
- attr_reader :object, :graphql_context, :extension_options, :default_decorator_context
26
+ attr_reader :object, :field_context, :default_decorator_context
28
27
 
29
28
  def decorator_class
30
- if extension_options[:decorator_class]
31
- extension_options[:decorator_class]
32
- elsif extension_options[:decorator_evaluator]
33
- extension_options[:decorator_evaluator].call(object)
29
+ if field_context.options[:decorator_class]
30
+ field_context.options[:decorator_class]
31
+ elsif field_context.options[:decorator_evaluator]
32
+ field_context.options[:decorator_evaluator].call(object)
34
33
  else
35
34
  resolve_decorator_class
36
35
  end
37
36
  end
38
37
 
39
38
  def decorator_context_evaluator
40
- extension_options[:decorator_context_evaluator] || resolve_decorator_context_evaluator
39
+ field_context.options[:decorator_context_evaluator] || resolve_decorator_context_evaluator
41
40
  end
42
41
 
43
42
  private
@@ -65,7 +64,7 @@ module GraphQL
65
64
  end
66
65
 
67
66
  def resolve_type
68
- extension_options[:unresolved_type]&.resolve_type(object, graphql_context)
67
+ field_context.options[:unresolved_type]&.resolve_type(object, field_context.context)
69
68
  end
70
69
  end
71
70
  end
@@ -1,5 +1,6 @@
1
1
  module GraphQL
2
2
  module Decorate
3
+ # Extends GraphQL::Schema::Object classes with methods to set the desired decorator class and context.
3
4
  module ObjectIntegration
4
5
  # Decorate the type with a decorator class.
5
6
  # @param klass [Class] Class the object should be decorated with.
@@ -1,37 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module Decorate
4
+ # Extracts configured decorator attributes from a GraphQL::Schema::Object type.
4
5
  class TypeAttributes
6
+ # @return [GraphQL::Schema::Object] type to extract decorator attributes from
5
7
  attr_reader :type
6
8
 
9
+ # @param [GraphQL::Schema::Object] type to extract decorator attributes from
7
10
  def initialize(type)
8
11
  @type = type
9
12
  end
10
13
 
14
+ # @return [Class, nil] Decorator class for the type if available
11
15
  def decorator_class
12
16
  get_attribute(:decorator_class)
13
17
  end
14
18
 
19
+ # @return [Proc, nil] Decorator evaluator for the type if available
15
20
  def decorator_evaluator
16
21
  get_attribute(:decorator_evaluator)
17
22
  end
18
23
 
24
+ # @return [Proc, nil] Decorator context evaluator for the type if available
19
25
  def decorator_context_evaluator
20
26
  get_attribute(:decorator_context_evaluator)
21
27
  end
22
28
 
29
+ # @return [GraphQL::Schema::Object, nil] Decorator evaluator for the type if available
23
30
  def unresolved_type
24
31
  unresolved_type? ? type : nil
25
32
  end
26
33
 
34
+ # @return [Boolean] True if type is not yet resolved, false if it is resolved
27
35
  def unresolved_type?
28
36
  type.respond_to?(:resolve_type)
29
37
  end
30
38
 
39
+ # @return [Boolean] True if type is resolved, false if it is not resolved
31
40
  def resolved_type?
32
41
  !unresolved_type?
33
42
  end
34
43
 
44
+ # @return [Boolean] True if type is a connection, false if it is resolved
35
45
  def connection?
36
46
  resolved_type? && type.respond_to?(:node_type)
37
47
  end
@@ -42,7 +52,7 @@ module GraphQL
42
52
  if connection?
43
53
  type.node_type.respond_to?(name) && type.node_type.public_send(name)
44
54
  elsif resolved_type?
45
- type.respond_to?(name) && type.public_send(name)
55
+ type.respond_to?(name) ? type.public_send(name) : nil
46
56
  end
47
57
  end
48
58
  end
@@ -1,5 +1,6 @@
1
1
  module GraphQL
2
2
  module Decorate
3
- VERSION = "0.1.1"
3
+ # Current version number
4
+ VERSION = "0.2.1"
4
5
  end
5
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-decorate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Brook
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-26 00:00:00.000000000 Z
11
+ date: 2021-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -74,7 +74,7 @@ dependencies:
74
74
  version: '3.0'
75
75
  description:
76
76
  email:
77
- - bbrook@truecar.com
77
+ - bbrook154@gmail.com
78
78
  executables: []
79
79
  extensions: []
80
80
  extra_rdoc_files: []
@@ -91,13 +91,15 @@ files:
91
91
  - graphql-decorate.gemspec
92
92
  - lib/graphql/decorate.rb
93
93
  - lib/graphql/decorate/configuration.rb
94
+ - lib/graphql/decorate/connection.rb
95
+ - lib/graphql/decorate/field_context.rb
94
96
  - lib/graphql/decorate/field_extension.rb
95
97
  - lib/graphql/decorate/field_integration.rb
98
+ - lib/graphql/decorate/object.rb
96
99
  - lib/graphql/decorate/object_integration.rb
97
- - lib/graphql/decorate/resolution.rb
98
100
  - lib/graphql/decorate/type_attributes.rb
99
101
  - lib/graphql/decorate/version.rb
100
- homepage: https://git.corp.tc/bbrook/graphql-decorate
102
+ homepage: https://www.github.com/TrueCar/graphql-decorate
101
103
  licenses:
102
104
  - MIT
103
105
  metadata: {}