graphiti_graphql 0.1.4 → 0.1.8

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
  SHA256:
3
- metadata.gz: 5bee75fe735608862a522a16be4a9ab31900b45af74ff48d4294d114227bd543
4
- data.tar.gz: ade635fd51be3820845bfccb79bd17c2b5bcff0c961a930910299dda6c90fad2
3
+ metadata.gz: 40128f0eaf0ad7859fa35c67bb73b2a2fccf51829bb3914877ce0c19730def91
4
+ data.tar.gz: 6f3fe80c618aaa093dd2daec4aa726621c32d2228bb92ddfdfd00f6a610490af
5
5
  SHA512:
6
- metadata.gz: e6720bf46431df3c5f5c2906fdf94aac13e4255cdfcdb2c2eb1fbd40d58bd2e28b231a9e2238d13e5ec7aaab9bd9ff60f86de9086972e90ec372bd12fe902978
7
- data.tar.gz: 0aff8b2e2459bd1c94b674dce2ce9e618f63c1b0dffc3fe49a1766c59b6aa692db2d14ca05d45747f990069d2bf39ee1ac3d9413732ba14c88ffeebbf20fa351
6
+ metadata.gz: f957bb6f2092f052d683c94008940823a29cb0a995d4741eaadbf2b87f0e3585268e01819a7fde057afd0a99c0f2b4dd14d2fc76903f3e44cc51c05724a0bd69
7
+ data.tar.gz: 30c3b26190d74c0559553458d05fdd36367fb9742b320322138d0f7a9ac503775d14edddb3a25b28276b5c099588186554f6ac686da0095175c557a921c1029e
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphiti_graphql (0.1.2)
4
+ graphiti_graphql (0.1.6)
5
5
  activesupport (>= 4.1)
6
- graphiti (>= 1.2.36)
6
+ graphiti (~> 1.3)
7
7
  graphql (~> 1.12)
8
8
 
9
9
  GEM
@@ -28,13 +28,13 @@ GEM
28
28
  dry-configurable (0.12.1)
29
29
  concurrent-ruby (~> 1.0)
30
30
  dry-core (~> 0.5, >= 0.5.0)
31
- dry-container (0.7.2)
31
+ dry-container (0.8.0)
32
32
  concurrent-ruby (~> 1.0)
33
33
  dry-configurable (~> 0.1, >= 0.1.3)
34
- dry-core (0.5.0)
34
+ dry-core (0.7.1)
35
35
  concurrent-ruby (~> 1.0)
36
- dry-inflector (0.2.0)
37
- dry-logic (1.1.0)
36
+ dry-inflector (0.2.1)
37
+ dry-logic (1.2.0)
38
38
  concurrent-ruby (~> 1.0)
39
39
  dry-core (~> 0.5, >= 0.5)
40
40
  dry-types (1.5.1)
@@ -44,7 +44,7 @@ GEM
44
44
  dry-inflector (~> 0.1, >= 0.1.2)
45
45
  dry-logic (~> 1.0, >= 1.0.2)
46
46
  google-protobuf (3.15.2)
47
- graphiti (1.2.36)
47
+ graphiti (1.3.0)
48
48
  activesupport (>= 4.1)
49
49
  concurrent-ruby (~> 1.0)
50
50
  dry-types (>= 0.15.0, < 2.0)
@@ -137,4 +137,4 @@ DEPENDENCIES
137
137
  standardrb
138
138
 
139
139
  BUNDLED WITH
140
- 2.0.2
140
+ 2.2.16
data/bin/bundle CHANGED
@@ -31,7 +31,7 @@ m = Module.new do
31
31
  bundler_version = a
32
32
  end
33
33
  next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
- bundler_version = $1 || ">= 0.a"
34
+ bundler_version = $1
35
35
  update_index = i
36
36
  end
37
37
  bundler_version
@@ -61,32 +61,41 @@ m = Module.new do
61
61
  end
62
62
 
63
63
  def bundler_version
64
- @bundler_version ||= begin
64
+ @bundler_version ||=
65
65
  env_var_version || cli_arg_version ||
66
- lockfile_version || "#{Gem::Requirement.default}.a"
67
- end
66
+ lockfile_version
67
+ end
68
+
69
+ def bundler_requirement
70
+ return "#{Gem::Requirement.default}.a" unless bundler_version
71
+
72
+ bundler_gem_version = Gem::Version.new(bundler_version)
73
+
74
+ requirement = bundler_gem_version.approximate_recommendation
75
+
76
+ return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
77
+
78
+ requirement += ".a" if bundler_gem_version.prerelease?
79
+
80
+ requirement
68
81
  end
69
82
 
70
83
  def load_bundler!
71
84
  ENV["BUNDLE_GEMFILE"] ||= gemfile
72
85
 
73
- # must dup string for RG < 1.8 compatibility
74
- activate_bundler(bundler_version.dup)
86
+ activate_bundler
75
87
  end
76
88
 
77
- def activate_bundler(bundler_version)
78
- if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79
- bundler_version = "< 2"
80
- end
89
+ def activate_bundler
81
90
  gem_error = activation_error_handling do
82
- gem "bundler", bundler_version
91
+ gem "bundler", bundler_requirement
83
92
  end
84
93
  return if gem_error.nil?
85
94
  require_error = activation_error_handling do
86
95
  require "bundler/version"
87
96
  end
88
- return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89
- warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
97
+ return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
98
+ warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
90
99
  exit 42
91
100
  end
92
101
 
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_dependency "graphiti", ">= 1.2.36"
30
+ spec.add_dependency "graphiti", "~> 1.3"
31
31
  spec.add_dependency "activesupport", ">= 4.1"
32
32
  spec.add_dependency "graphql", "~> 1.12"
33
33
 
@@ -13,7 +13,7 @@ require "graphiti_graphql/util"
13
13
 
14
14
  module GraphitiGraphQL
15
15
  class Configuration
16
- attr_accessor :schema_reloading
16
+ attr_accessor :schema_reloading, :federation_application_controller
17
17
 
18
18
  def initialize
19
19
  self.schema_reloading = true
@@ -74,6 +74,10 @@ module GraphitiGraphQL
74
74
  @config ||= Configuration.new
75
75
  end
76
76
 
77
+ def self.configure
78
+ yield config
79
+ end
80
+
77
81
  def self.schemas
78
82
  @schemas ||= SchemaProxy.new
79
83
  end
@@ -64,12 +64,15 @@ module GraphitiGraphQL
64
64
  end
65
65
 
66
66
  initializer "graphiti_graphql.define_controller" do
67
- # rubocop:disable Lint/ConstantDefinitionInBlock(Standard)
68
- class GraphitiGraphQL::ExecutionController < ::ApplicationController
69
- register_exception Graphiti::Errors::UnreadableAttribute, message: true
70
- def execute
71
- params = request.params # avoid strong_parameters
72
- render json: Graphiti.gql(params[:query], params[:variables])
67
+ GraphitiGraphQL::Engine.reloader_class.to_prepare do
68
+ app_controller = GraphitiGraphQL.config.federation_application_controller || ::ApplicationController
69
+ # rubocop:disable Lint/ConstantDefinitionInBlock(Standard)
70
+ class GraphitiGraphQL::ExecutionController < app_controller
71
+ register_exception Graphiti::Errors::UnreadableAttribute, message: true
72
+ def execute
73
+ params = request.params # avoid strong_parameters
74
+ render json: Graphiti.gql(params[:query], params[:variables])
75
+ end
73
76
  end
74
77
  end
75
78
  end
@@ -21,6 +21,18 @@ module GraphitiGraphQL
21
21
  @relationships[name].instance_eval(&blk)
22
22
  end
23
23
  end
24
+
25
+ def polymorphic?
26
+ @type_name.is_a?(Hash)
27
+ end
28
+
29
+ def klass_name
30
+ if polymorphic?
31
+ "I#{@relationships.keys[0].to_s.camelize}"
32
+ else
33
+ @type_name
34
+ end
35
+ end
24
36
  end
25
37
  end
26
38
  end
@@ -15,6 +15,19 @@ module GraphitiGraphQL
15
15
 
16
16
  @federated_relationship.params_block&.call(@params)
17
17
 
18
+ if (first = @params.delete(:first))
19
+ @params[:page] ||= {}
20
+ @params[:page][:size] = first
21
+ end
22
+ if (after = @params.delete(:after))
23
+ @params[:page] ||= {}
24
+ @params[:page][:after] = after
25
+ end
26
+ if (before = @params.delete(:before))
27
+ @params[:page] ||= {}
28
+ @params[:page][:before] = before
29
+ end
30
+
18
31
  if ids.length > 1 && @params[:page]
19
32
  raise Graphiti::Errors::UnsupportedPagination
20
33
  elsif !@params[:page]
@@ -64,18 +64,30 @@ module GraphitiGraphQL
64
64
  # * Add to the list of external graphql-ruby types we need in schema
65
65
  # * Add a gql-specific attribute to the serializer that gives apollo
66
66
  # the representation it needs.
67
- def federated_belongs_to(name, type: nil, foreign_key: nil)
67
+ def federated_belongs_to(name, type: nil, foreign_key: nil, foreign_type: nil)
68
68
  type ||= name.to_s.camelize
69
69
  foreign_key ||= :"#{name.to_s.underscore}_id"
70
70
  resource = FederatedResource.new(type)
71
71
  federated_resources << resource
72
72
  resource.add_relationship(:belongs_to, name, self, foreign_key)
73
73
 
74
+ foreign_type ||= :"#{name.to_s.underscore}_type" if resource.polymorphic?
75
+
74
76
  opts = {readable: :gql?, only: [:readable], schema: false}
75
77
  attribute name, :hash, opts do
76
78
  prc = self.class.attribute_blocks[foreign_key]
77
79
  fk = prc ? instance_eval(&prc) : @object.send(foreign_key)
78
- {__typename: type, id: fk.to_s}
80
+
81
+ typename = type
82
+ if resource.polymorphic?
83
+ prc = self.class.attribute_blocks[foreign_type]
84
+ ft = prc ? instance_eval(&prc) : @object.send(foreign_type)
85
+ typename = type[ft]
86
+ end
87
+
88
+ if fk && typename.present?
89
+ {__typename: typename, id: fk.to_s}
90
+ end
79
91
  end
80
92
  end
81
93
  end
@@ -66,19 +66,39 @@ module GraphitiGraphQL
66
66
  pre_registered = !!type_registry[federated_resource.type_name]
67
67
  type_class = if pre_registered
68
68
  type_registry[federated_resource.type_name][:type]
69
+ elsif federated_resource.polymorphic?
70
+ add_federated_resource_interface(federated_resource)
69
71
  else
70
- add_federated_resource_type(federated_resource.type_name)
72
+ add_federated_resource_type(federated_resource.klass_name)
71
73
  end
72
74
 
73
75
  yield type_class, federated_resource
74
76
  end
75
77
  end
76
78
 
77
- def add_federated_resource_type(klass_name)
79
+ def add_federated_resource_interface(federated_resource)
80
+ interface = define_polymorphic_federated_resource_interface(federated_resource.klass_name)
81
+ federated_resource.type_name.values.each do |name|
82
+ add_federated_resource_type(name, interface: interface)
83
+ end
84
+ interface
85
+ end
86
+
87
+ def define_polymorphic_federated_resource_interface(klass_name)
88
+ interface = Module.new
89
+ interface.send(:include, @schema.class.base_interface)
90
+ interface.graphql_name(klass_name)
91
+ interface.field :id, String, null: false, external: true
92
+ type_registry[klass_name] = {type: interface, interface: true}
93
+ interface
94
+ end
95
+
96
+ def add_federated_resource_type(klass_name, interface: nil)
78
97
  federated_type = Class.new(@schema.class.base_object)
79
98
  federated_type.graphql_name klass_name
80
99
  federated_type.key(fields: "id")
81
100
  federated_type.extend_type
101
+ federated_type.implements(interface) if interface
82
102
  federated_type.field :id, String, null: false, external: true
83
103
  federated_type.class_eval do
84
104
  def self.resolve_reference(reference, _context, _lookup)
@@ -161,7 +181,7 @@ module GraphitiGraphQL
161
181
 
162
182
  local_types.each do |local|
163
183
  local.field relationship.name,
164
- type_registry[federated_resource.type_name][:type],
184
+ type_registry[federated_resource.klass_name][:type],
165
185
  null: true
166
186
  end
167
187
  end
@@ -282,11 +282,23 @@ module GraphitiGraphQL
282
282
  def gather_pages(params, selection, variable_hash, chained_name = nil)
283
283
  pages = {}.tap do |p|
284
284
  selection.arguments.each do |arg|
285
- if arg.name == "page"
285
+ if ["page", "first", "after", "before"].include?(arg.name)
286
286
  value = if arg.value.respond_to?(:name) # is a variable
287
- variable_hash[arg.value.name].to_h
287
+ variable_hash[arg.value.name]
288
288
  else
289
- arg.value.to_h
289
+ arg.value
290
+ end
291
+
292
+ next unless value
293
+
294
+ value = if arg.name == "first"
295
+ {size: value}
296
+ elsif arg.name == "after"
297
+ {after: value}
298
+ elsif arg.name == "before"
299
+ {before: value}
300
+ else
301
+ value.to_h
290
302
  end
291
303
 
292
304
  if chained_name
@@ -304,6 +316,13 @@ module GraphitiGraphQL
304
316
  params[:page] ||= {}
305
317
  params[:page].merge!(pages)
306
318
  end
319
+
320
+ (selection.try(:selections) || []).each do |sub|
321
+ if sub.try(:name) == "pageInfo"
322
+ params[:fields] ||= {}
323
+ params[:fields][:page_info] = sub.selections.map(&:name).map(&:underscore).join(",")
324
+ end
325
+ end
307
326
  end
308
327
 
309
328
  def gather_stats(params, selection, variable_hash, chained_name = nil)
@@ -93,6 +93,7 @@ module GraphitiGraphQL
93
93
  query_class = Class.new(existing_query || self.class.base_object)
94
94
  # NB MUST be Query or federation-ruby will break things
95
95
  query_class.graphql_name "Query"
96
+ query_class.field_class BaseField
96
97
 
97
98
  get_entrypoints(entrypoint_resources).each do |resource|
98
99
  next if resource.remote?
@@ -145,22 +146,46 @@ module GraphitiGraphQL
145
146
  [type],
146
147
  "List #{resource.graphql_class_name(false).pluralize}",
147
148
  null: false
149
+
150
+ # Stats currently only supported on top level
148
151
  if top_level
152
+ klass.field :page_info, PageInfoType, null: false
149
153
  klass.field :stats, generate_stat_class(resource), null: false
150
154
  end
151
155
  register(name, klass)
152
156
  klass
153
157
  end
154
158
 
159
+ # def edge_type(name, type)
160
+ # if (registered = type_registry[name])
161
+ # return registered[:type]
162
+ # end
163
+
164
+ # klass = Class.new(BaseObject) do
165
+ # graphql_name "#{name}Edge"
166
+ # field :cursor, String, null: false
167
+ # field :node, type, null: false
168
+ # end
169
+ # type_registry[name] = {type: klass}
170
+ # klass
171
+ # end
172
+
155
173
  def add_index(query_class, resource)
156
174
  field_name = resource.graphql_entrypoint.to_s.underscore.to_sym
157
175
  field = query_class.field field_name,
158
176
  generate_connection_type(resource, top_level: true),
159
- null: false
177
+ null: false,
178
+ connection: false
160
179
  @query_fields[field_name] = resource
161
180
  define_arguments_for_sideload_field(field, resource)
162
181
  end
163
182
 
183
+ def apply_connection_args(field)
184
+ field.argument :after, "String", "Cursor to paginate after", required: false
185
+ field.argument :before, "String", "Cursor to paginate before", required: false
186
+ field.argument :first, "Int", "Same as page.size", required: false
187
+ end
188
+
164
189
  def add_show(query_class, resource)
165
190
  field_name = resource.graphql_entrypoint.to_s.underscore.singularize.to_sym
166
191
  field = query_class.field field_name,
@@ -222,6 +247,7 @@ module GraphitiGraphQL
222
247
  field.argument :sort, [sort_type], required: false
223
248
  end
224
249
  field.argument :page, PageType, required: false
250
+ apply_connection_args(field)
225
251
 
226
252
  unless resource.filters.empty?
227
253
  filter_type = generate_filter_type(field, resource)
@@ -375,6 +401,8 @@ module GraphitiGraphQL
375
401
  end
376
402
  end
377
403
 
404
+ klass.field :_cursor, String, null: false
405
+
378
406
  register(type_name, klass, resource, poly_parent)
379
407
 
380
408
  resource.sideloads.each_pair do |name, sideload|
@@ -480,6 +508,16 @@ module GraphitiGraphQL
480
508
  graphql_name "Page"
481
509
  argument :size, Int, required: false
482
510
  argument :number, Int, required: false
511
+ argument :after, String, required: false
512
+ argument :before, String, required: false
513
+ end
514
+
515
+ class PageInfoType < BaseObject
516
+ graphql_name "PageInfo"
517
+ field :has_next_page, Boolean, null: false
518
+ field :has_previous_page, Boolean, null: false
519
+ field :start_cursor, String, null: false
520
+ field :end_cursor, String, null: false
483
521
  end
484
522
 
485
523
  class SortDirType < GraphQL::Schema::Enum
@@ -1,3 +1,3 @@
1
1
  module GraphitiGraphQL
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.8"
3
3
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphiti_graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Richmond
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-07 00:00:00.000000000 Z
11
+ date: 2021-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphiti
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.2.36
19
+ version: '1.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.2.36
26
+ version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -274,7 +274,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
274
274
  - !ruby/object:Gem::Version
275
275
  version: '0'
276
276
  requirements: []
277
- rubygems_version: 3.0.3
277
+ rubygems_version: 3.2.22
278
278
  signing_key:
279
279
  specification_version: 4
280
280
  summary: GraphQL support for Graphiti