graphql-client 0.7.0 → 0.8.0

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: bd882791666554b4b6999b5e6e1089187eb06e9a
4
- data.tar.gz: 5c1e142aee92b113edef6c34a90484ff32b2fd0e
3
+ metadata.gz: 9c735cc6d34d7372e777934b15cbf86540cf994a
4
+ data.tar.gz: 329f6769cf02065e726dd26e9006cb1143f3f8df
5
5
  SHA512:
6
- metadata.gz: 242cd9508205d68cb2459a78bcd689a986c4317478113923d8fbd23d015bf8c936fd84619410228404699a7c229377f6333f857f216853d9991b32603e34443d
7
- data.tar.gz: 74fb38b0777b0df123df5c5a09a6e1caf5f69ec3f5f765c859d041900c58e6403cebd0a59c882095524ba18cf08ab0e04dcfca7164b39c6d2e291e8f845b15f1
6
+ metadata.gz: fd69bd130b837dff72de557d1b0c51e7a4f0b499af231af00d8b2df65a638116021f45660be83c8695aa27bbf808741db5317d4791e68f6bf0db9f059dbf9273
7
+ data.tar.gz: 20d75c1fa9d08f56a096328cf499e163eea4b7d13bfc9767f8fa743004e87c9a611d32d6533cbc0f28d72770b41635eff526549baf81bd52cc319ed0437ccb4c
@@ -3,9 +3,12 @@ require "active_support/inflector"
3
3
  require "active_support/notifications"
4
4
  require "graphql"
5
5
  require "graphql/client/collocated_enforcement"
6
+ require "graphql/client/definition"
6
7
  require "graphql/client/definition_variables"
7
8
  require "graphql/client/error"
8
9
  require "graphql/client/errors"
10
+ require "graphql/client/fragment_definition"
11
+ require "graphql/client/operation_definition"
9
12
  require "graphql/client/query_result"
10
13
  require "graphql/client/query_typename"
11
14
  require "graphql/client/response"
@@ -88,96 +91,6 @@ module GraphQL
88
91
  @enforce_collocated_callers = enforce_collocated_callers
89
92
  end
90
93
 
91
- # Definitions are constructed by Client.parse and wrap a parsed AST of the
92
- # query string as well as hold references to any external query definition
93
- # dependencies.
94
- #
95
- # Definitions MUST be assigned to a constant.
96
- class Definition < Module
97
- def self.for(node:, **kargs)
98
- case node
99
- when Language::Nodes::OperationDefinition
100
- OperationDefinition.new(node: node, **kargs)
101
- when Language::Nodes::FragmentDefinition
102
- FragmentDefinition.new(node: node, **kargs)
103
- else
104
- raise TypeError, "expected node to be a definition type, but was #{node.class}"
105
- end
106
- end
107
-
108
- def initialize(node:, document:, schema:, document_types:, source_location:, enforce_collocated_callers:)
109
- @definition_node = node
110
- @document = document
111
- @schema = schema
112
- @document_types = document_types
113
- @source_location = source_location
114
- @enforce_collocated_callers = enforce_collocated_callers
115
- end
116
-
117
- # Internal: Get underlying operation or fragment defintion AST node for
118
- # definition.
119
- #
120
- # Returns OperationDefinition or FragmentDefinition object.
121
- attr_reader :definition_node
122
-
123
- # Public: Global name of definition in client document.
124
- #
125
- # Returns a GraphQL safe name of the Ruby constant String.
126
- #
127
- # "Users::UserQuery" #=> "Users__UserQuery"
128
- #
129
- # Returns String.
130
- def definition_name
131
- return @definition_name if defined?(@definition_name)
132
-
133
- if name
134
- @definition_name = name.gsub("::", "__").freeze
135
- else
136
- "#{self.class.name}_#{object_id}".gsub("::", "__").freeze
137
- end
138
- end
139
-
140
- # Public: Get document with only the definitions needed to perform this
141
- # operation.
142
- #
143
- # Returns GraphQL::Language::Nodes::Document with one OperationDefinition
144
- # and any FragmentDefinition dependencies.
145
- attr_reader :document
146
-
147
- # Internal: Mapping of document nodes to schema types.
148
- attr_reader :document_types
149
-
150
- attr_reader :schema
151
-
152
- # Public: Returns the Ruby source filename and line number containing this
153
- # definition was not defined in Ruby.
154
- #
155
- # Returns Array pair of [String, Fixnum].
156
- attr_reader :source_location
157
-
158
- attr_reader :enforce_collocated_callers
159
-
160
- def new(*args)
161
- type.new(*args)
162
- end
163
-
164
- def type
165
- # TODO: Fix type indirection
166
- @type ||= GraphQL::Client::QueryResult.wrap(self, definition_node, name: "#{name}.type")
167
- end
168
- end
169
-
170
- # Specific operation definition subtype for queries, mutations or
171
- # subscriptions.
172
- class OperationDefinition < Definition
173
- # Public: Alias for definition name.
174
- alias operation_name definition_name
175
- end
176
-
177
- # Specific fragment definition subtype.
178
- class FragmentDefinition < Definition
179
- end
180
-
181
94
  def parse(str, filename = nil, lineno = nil)
182
95
  if filename.nil? && lineno.nil?
183
96
  location = caller_locations(1, 1).first
@@ -3,6 +3,10 @@ require "graphql/client/error"
3
3
 
4
4
  module GraphQL
5
5
  class Client
6
+
7
+ # Collcation will not be enforced if a stack trace includes any of these gems.
8
+ WHITELISTED_GEM_NAMES = %w{pry byebug}
9
+
6
10
  # Raised when method is called from outside the expected file scope.
7
11
  class NonCollocatedCallerError < Error; end
8
12
 
@@ -30,7 +34,8 @@ module GraphQL
30
34
  return super(*args, &block) if Thread.current[:query_result_caller_location_ignore]
31
35
 
32
36
  locations = caller_locations(1, 1)
33
- if locations.first.path != path
37
+
38
+ if (locations.first.path != path) && !(caller_locations.any? { |cl| WHITELISTED_GEM_NAMES.any? { |g| cl.path.include?("gems/#{g}") } })
34
39
  error = NonCollocatedCallerError.new("#{method} was called outside of '#{path}' https://git.io/v1syX")
35
40
  error.set_backtrace(caller(1))
36
41
  raise error
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Client
4
+ # Definitions are constructed by Client.parse and wrap a parsed AST of the
5
+ # query string as well as hold references to any external query definition
6
+ # dependencies.
7
+ #
8
+ # Definitions MUST be assigned to a constant.
9
+ class Definition < Module
10
+ def self.for(node:, **kargs)
11
+ case node
12
+ when Language::Nodes::OperationDefinition
13
+ OperationDefinition.new(node: node, **kargs)
14
+ when Language::Nodes::FragmentDefinition
15
+ FragmentDefinition.new(node: node, **kargs)
16
+ else
17
+ raise TypeError, "expected node to be a definition type, but was #{node.class}"
18
+ end
19
+ end
20
+
21
+ def initialize(node:, document:, schema:, document_types:, source_location:, enforce_collocated_callers:)
22
+ @definition_node = node
23
+ @document = document
24
+ @schema = schema
25
+ @document_types = document_types
26
+ @source_location = source_location
27
+ @enforce_collocated_callers = enforce_collocated_callers
28
+ end
29
+
30
+ # Internal: Get underlying operation or fragment defintion AST node for
31
+ # definition.
32
+ #
33
+ # Returns OperationDefinition or FragmentDefinition object.
34
+ attr_reader :definition_node
35
+
36
+ # Public: Global name of definition in client document.
37
+ #
38
+ # Returns a GraphQL safe name of the Ruby constant String.
39
+ #
40
+ # "Users::UserQuery" #=> "Users__UserQuery"
41
+ #
42
+ # Returns String.
43
+ def definition_name
44
+ return @definition_name if defined?(@definition_name)
45
+
46
+ if name
47
+ @definition_name = name.gsub("::", "__").freeze
48
+ else
49
+ "#{self.class.name}_#{object_id}".gsub("::", "__").freeze
50
+ end
51
+ end
52
+
53
+ # Public: Get document with only the definitions needed to perform this
54
+ # operation.
55
+ #
56
+ # Returns GraphQL::Language::Nodes::Document with one OperationDefinition
57
+ # and any FragmentDefinition dependencies.
58
+ attr_reader :document
59
+
60
+ # Internal: Mapping of document nodes to schema types.
61
+ attr_reader :document_types
62
+
63
+ attr_reader :schema
64
+
65
+ # Public: Returns the Ruby source filename and line number containing this
66
+ # definition was not defined in Ruby.
67
+ #
68
+ # Returns Array pair of [String, Fixnum].
69
+ attr_reader :source_location
70
+
71
+ attr_reader :enforce_collocated_callers
72
+
73
+ def new(*args)
74
+ type.new(*args)
75
+ end
76
+
77
+ def type
78
+ # TODO: Fix type indirection
79
+ @type ||= GraphQL::Client::QueryResult.wrap(self, definition_node, name: "#{name}.type")
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/definition"
4
+
5
+ module GraphQL
6
+ class Client
7
+ # Specific fragment definition subtype.
8
+ class FragmentDefinition < Definition
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/definition"
4
+
5
+ module GraphQL
6
+ class Client
7
+ # Specific operation definition subtype for queries, mutations or
8
+ # subscriptions.
9
+ class OperationDefinition < Definition
10
+ # Public: Alias for definition name.
11
+ alias operation_name definition_name
12
+ end
13
+ end
14
+ end
@@ -227,12 +227,16 @@ module GraphQL
227
227
  # Returns Errors collection.
228
228
  attr_reader :errors
229
229
 
230
- attr_reader :data
231
- alias to_h data
232
-
233
230
  attr_reader :__typename
234
231
  alias typename __typename
235
232
 
233
+ # Public: Returns the raw response data
234
+ #
235
+ # Returns Hash
236
+ def to_h
237
+ @data
238
+ end
239
+
236
240
  def type_of?(*types)
237
241
  types.any? do |type|
238
242
  if type = self.class.schema.types.fetch(type.to_s, nil)
@@ -272,7 +276,7 @@ module GraphQL
272
276
  raise UnimplementedFieldError, "undefined field `#{e.name}' on #{type} type. https://git.io/v1y3m"
273
277
  end
274
278
 
275
- if data[field.name]
279
+ if @data[field.name]
276
280
  error_class = ImplicitlyFetchedFieldError
277
281
  message = "implicitly fetched field `#{field.name}' on #{type} type. https://git.io/v1yGL"
278
282
  else
@@ -44,14 +44,14 @@ module GraphQL
44
44
  #
45
45
  # Returns nothing.
46
46
  def eager_load!
47
- return unless File.directory?(path)
47
+ return unless File.directory?(load_path)
48
48
 
49
- Dir.entries(path).each do |entry|
49
+ Dir.entries(load_path).each do |entry|
50
50
  next if entry == "." || entry == ".."
51
51
  name = entry.sub(/(\.\w+)+$/, "").camelize.to_sym
52
- if ViewModule.valid_constant_name?(name) && loadable_const_defined?(name)
53
- mod = const_get(name, false)
54
- mod.eager_load!
52
+ if ViewModule.valid_constant_name?(name)
53
+ mod = const_defined?(name, false) ? const_get(name) : load_and_set_module(name)
54
+ mod.eager_load! if mod
55
55
  end
56
56
  end
57
57
 
@@ -73,76 +73,67 @@ module GraphQL
73
73
  name.to_s =~ /^[A-Z][a-zA-Z0-9_]*$/
74
74
  end
75
75
 
76
- # Public: Override constant defined to check if constant name matches a
77
- # view directory or template namespace.
78
- #
79
- # name - String or Symbol constant name
80
- # inherit - If the lookup will also search the ancestors (default: true)
81
- #
82
- # Returns true if definition is found, otherwise false.
83
- # def const_defined?(name, inherit = true)
84
- # if super(name.to_sym, inherit)
85
- # true
86
- # elsif const_path(name)
87
- # true
88
- # else
89
- # false
90
- # end
91
- # end
92
-
93
- def loadable_const_defined?(name)
94
- if const_defined?(name.to_sym, false)
95
- true
96
- elsif const_path(name)
97
- true
98
- else
99
- false
100
- end
101
- end
102
-
103
- # Public: Source location that defined the Module.
76
+ # Public: Directory to retrieve nested GraphQL definitions from.
104
77
  #
105
78
  # Returns absolute String path under app/views.
106
- attr_accessor :path
79
+ attr_accessor :load_path
80
+ alias_method :path=, :load_path=
81
+ alias_method :path, :load_path
107
82
 
108
- # Internal: Detect source location for constant name.
109
- #
110
- # name - String or Symbol constant name
83
+ # Public: if this module was defined by a view
111
84
  #
112
- # Examples
113
- #
114
- # Views.const_path(:Users) #=> "app/views/users"
115
- # Views::Users.const_path(:Show) #=> "app/views/users/show.html.erb"
116
- # Views::Users.const_path(:Profile) #=> "app/views/users/_profile.html.erb"
117
- #
118
- # Returns String absolute path to file, otherwise nil.
119
- def const_path(name)
120
- pathname = ActiveSupport::Inflector.underscore(name.to_s)
121
- Dir[File.join(path, "{#{pathname},_#{pathname}}{/,.*}")].map { |fn| File.expand_path(fn) }.first
122
- end
85
+ # Returns absolute String path under app/views.
86
+ attr_accessor :source_path
123
87
 
124
88
  # Internal: Initialize new module for constant name and load ERB statics.
125
89
  #
126
- # path - String path of directory or erb file.
90
+ # name - String or Symbol constant name.
127
91
  #
128
92
  # Examples
129
93
  #
130
- # load_module("app/views/users")
131
- # load_module("app/views/users/show.html.erb")
94
+ # Views::Users.load_module(:Profile)
95
+ # Views::Users::Profile.load_module(:Show)
132
96
  #
133
97
  # Returns new Module implementing Loadable concern.
134
- def load_module(path)
135
- mod = Module.new
98
+ def load_module(name)
99
+ pathname = ActiveSupport::Inflector.underscore(name.to_s)
100
+ path = Dir[File.join(load_path, "{#{pathname},_#{pathname}}{.*}")].map { |fn| File.expand_path(fn) }.first
136
101
 
137
- if File.extname(path) == ".erb"
138
- contents = File.read(path)
139
- query, lineno = ViewModule.extract_graphql_section(contents)
140
- mod = client.parse(query, path, lineno) if query
141
- end
102
+ return if !path || File.extname(path) != ".erb"
142
103
 
104
+ contents = File.read(path)
105
+ query, lineno = ViewModule.extract_graphql_section(contents)
106
+ return unless query
107
+
108
+ mod = client.parse(query, path, lineno)
143
109
  mod.extend(ViewModule)
110
+ mod.load_path = File.join(load_path, pathname)
111
+ mod.source_path = path
144
112
  mod.client = client
145
- mod.path = path
113
+ mod
114
+ end
115
+
116
+ def placeholder_module(name)
117
+ dirname = File.join(load_path, ActiveSupport::Inflector.underscore(name.to_s))
118
+ return nil unless Dir.exist?(dirname)
119
+
120
+ Module.new.tap do |mod|
121
+ mod.extend(ViewModule)
122
+ mod.load_path = dirname
123
+ mod.client = client
124
+ end
125
+ end
126
+
127
+ def load_and_set_module(name)
128
+ placeholder = placeholder_module(name)
129
+ const_set(name, placeholder) if placeholder
130
+
131
+ mod = load_module(name)
132
+ return placeholder unless mod
133
+
134
+ remove_const(name) if placeholder
135
+ const_set(name, mod)
136
+ mod.unloadable
146
137
  mod
147
138
  end
148
139
 
@@ -152,16 +143,7 @@ module GraphQL
152
143
  #
153
144
  # Returns module or raises NameError if missing.
154
145
  def const_missing(name)
155
- path = const_path(name)
156
-
157
- if path
158
- mod = load_module(path)
159
- const_set(name, mod)
160
- mod.unloadable
161
- mod
162
- else
163
- super
164
- end
146
+ load_and_set_module(name) || super
165
147
  end
166
148
  end
167
149
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-30 00:00:00.000000000 Z
11
+ date: 2017-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -158,6 +158,7 @@ files:
158
158
  - README.md
159
159
  - lib/graphql/client.rb
160
160
  - lib/graphql/client/collocated_enforcement.rb
161
+ - lib/graphql/client/definition.rb
161
162
  - lib/graphql/client/definition_variables.rb
162
163
  - lib/graphql/client/document_types.rb
163
164
  - lib/graphql/client/error.rb
@@ -165,10 +166,12 @@ files:
165
166
  - lib/graphql/client/erubi_enhancer.rb
166
167
  - lib/graphql/client/erubis.rb
167
168
  - lib/graphql/client/erubis_enhancer.rb
169
+ - lib/graphql/client/fragment_definition.rb
168
170
  - lib/graphql/client/hash_with_indifferent_access.rb
169
171
  - lib/graphql/client/http.rb
170
172
  - lib/graphql/client/list.rb
171
173
  - lib/graphql/client/log_subscriber.rb
174
+ - lib/graphql/client/operation_definition.rb
172
175
  - lib/graphql/client/query_result.rb
173
176
  - lib/graphql/client/query_typename.rb
174
177
  - lib/graphql/client/railtie.rb
@@ -197,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
200
  version: '0'
198
201
  requirements: []
199
202
  rubyforge_project:
200
- rubygems_version: 2.6.11
203
+ rubygems_version: 2.5.2
201
204
  signing_key:
202
205
  specification_version: 4
203
206
  summary: GraphQL Client