graphql-pagination 2.4.0 → 2.5.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
  SHA256:
3
- metadata.gz: dd466ae9a7321da404337a0f4ae48af8565908cea8a4cf566b66346940966e3c
4
- data.tar.gz: 30a0ca37028db819874d92a7dcf81ec9510ed7458b641c3c31373dd1c9719661
3
+ metadata.gz: 9475b513e2ced37bbd798e3c254cd6e59e6ba3bb84fca82ceb3735b9202cc7f1
4
+ data.tar.gz: 6ff8b16a00b6e2036aac8e137913008fead15f6ed5f201758c371380b8e1801e
5
5
  SHA512:
6
- metadata.gz: 34547c5966e7f452c3b1609a6daf0047a43e355b19df32bf4467b1bdc2f52637aec61aaf5cbedc58c1e62a0fd145f506f9c8ffe48bffa4c6b27cc2488e4d8263
7
- data.tar.gz: eabdd62d97066e38640d7bbcb2753a0aa7ce1486c2b14b7ccfac7d8d13158c9f0234cd743d115fc87d08b4ed449f91dfa3b7750eb5db2ae87fe4a1db3d4cdb64
6
+ metadata.gz: 1c4cae67537d17e7de4e0844aff5c13a068c9e9b6b84bdd086b477229bcb80d9a88aafffad4d02ddaebc0d4719b903d8088d540a12af123a7a2e3a871a9677e5
7
+ data.tar.gz: c4e76b225701a6025e2924b4aa6600815272a26883a4990ae81c9607152032db965941f3fd6a91af92703f1825957b2cb367c9f768654896be6d925ac138a61f
data/.bundler-version CHANGED
@@ -1 +1 @@
1
- 2.6.3
1
+ 4.0.7
@@ -2,5 +2,5 @@
2
2
  <!--- Describe your changes in detail -->
3
3
  <!--- Why is this change required? What problem does it solve? -->
4
4
 
5
- ## Related issue(s) or PR(s)
6
- <!--- GH issue number -->
5
+ ## Related tickets(s), PR(s) or slack message:
6
+ <!--- Ticket/Issue/PR number or URL -->
@@ -8,7 +8,7 @@ jobs:
8
8
  auto-approve:
9
9
  runs-on: ubuntu-latest
10
10
  steps:
11
- - uses: hmarr/auto-approve-action@v3
11
+ - uses: hmarr/auto-approve-action@v4.0.0
12
12
  if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' || github.actor == 'renofidev' || contains(github.event.pull_request.labels.*.name, 'HOTFIX-AUTO-APPROVE') || contains(github.event.pull_request.labels.*.name, 'self-approve') || contains(github.event.pull_request.labels.*.name, 'dependencies')
13
13
  with:
14
14
  github-token: "${{ secrets.GITHUB_TOKEN }}"
@@ -11,10 +11,10 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- ruby-version: [3.3, 3.4]
14
+ ruby-version: [3.4, 4.0]
15
15
 
16
16
  steps:
17
- - uses: actions/checkout@v3
17
+ - uses: actions/checkout@v4
18
18
  - name: Set up Ruby
19
19
  uses: ruby/setup-ruby@v1
20
20
  with:
data/.gitignore CHANGED
@@ -6,9 +6,11 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /vendor/
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
12
13
 
13
14
  # Cached rubocop config files
14
- .rubocop-http*
15
+ .rubocop-*
16
+ .claude
data/Gemfile CHANGED
@@ -1,12 +1,14 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'kaminari-activerecord'
6
- gem 'kaminari-core'
7
- gem 'pry'
8
- gem 'rake'
9
- gem 'rspec'
10
- gem 'rubocop'
11
- gem 'rubocop-rake'
12
- gem 'rubocop-rspec'
5
+ gem "irb"
6
+ gem "kaminari-activerecord"
7
+ gem "kaminari-core"
8
+ gem "ostruct"
9
+ gem "pry"
10
+ gem "rake"
11
+ gem "rspec"
12
+ gem "standard"
13
+
14
+ gem "openssl"
data/Gemfile.lock CHANGED
@@ -1,105 +1,147 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql-pagination (2.4.0)
4
+ graphql-pagination (2.5.0)
5
5
  graphql (>= 2.4.7)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (8.0.1)
11
- activesupport (= 8.0.1)
12
- activerecord (8.0.1)
13
- activemodel (= 8.0.1)
14
- activesupport (= 8.0.1)
10
+ activemodel (8.1.3)
11
+ activesupport (= 8.1.3)
12
+ activerecord (8.1.3)
13
+ activemodel (= 8.1.3)
14
+ activesupport (= 8.1.3)
15
15
  timeout (>= 0.4.0)
16
- activesupport (8.0.1)
16
+ activesupport (8.1.3)
17
17
  base64
18
- benchmark (>= 0.3)
19
18
  bigdecimal
20
19
  concurrent-ruby (~> 1.0, >= 1.3.1)
21
20
  connection_pool (>= 2.2.5)
22
21
  drb
23
22
  i18n (>= 1.6, < 2)
23
+ json
24
24
  logger (>= 1.4.2)
25
25
  minitest (>= 5.1)
26
26
  securerandom (>= 0.3)
27
27
  tzinfo (~> 2.0, >= 2.0.5)
28
28
  uri (>= 0.13.1)
29
- ast (2.4.2)
30
- base64 (0.2.0)
31
- benchmark (0.4.0)
32
- bigdecimal (3.1.9)
29
+ ast (2.4.3)
30
+ base64 (0.3.0)
31
+ bigdecimal (4.1.1)
33
32
  coderay (1.1.3)
34
- concurrent-ruby (1.3.5)
35
- connection_pool (2.5.0)
36
- diff-lcs (1.5.1)
37
- drb (2.2.1)
38
- fiber-storage (1.0.0)
39
- graphql (2.4.9)
33
+ concurrent-ruby (1.3.6)
34
+ connection_pool (3.0.2)
35
+ date (3.5.1)
36
+ diff-lcs (1.6.2)
37
+ drb (2.2.3)
38
+ erb (6.0.2)
39
+ fiber-storage (1.0.1)
40
+ graphql (2.5.23)
40
41
  base64
41
42
  fiber-storage
42
43
  logger
43
- i18n (1.14.7)
44
+ i18n (1.14.8)
44
45
  concurrent-ruby (~> 1.0)
45
- json (2.9.1)
46
+ io-console (0.8.2)
47
+ irb (1.17.0)
48
+ pp (>= 0.6.0)
49
+ prism (>= 1.3.0)
50
+ rdoc (>= 4.0.0)
51
+ reline (>= 0.4.2)
52
+ json (2.19.3)
46
53
  kaminari-activerecord (1.2.2)
47
54
  activerecord
48
55
  kaminari-core (= 1.2.2)
49
56
  kaminari-core (1.2.2)
50
- language_server-protocol (3.17.0.4)
51
- logger (1.6.5)
57
+ language_server-protocol (3.17.0.5)
58
+ lint_roller (1.1.0)
59
+ logger (1.7.0)
52
60
  method_source (1.1.0)
53
- minitest (5.25.4)
54
- parallel (1.26.3)
55
- parser (3.3.7.1)
61
+ minitest (6.0.3)
62
+ drb (~> 2.0)
63
+ prism (~> 1.5)
64
+ openssl (4.0.1)
65
+ ostruct (0.6.3)
66
+ parallel (1.28.0)
67
+ parser (3.3.11.1)
56
68
  ast (~> 2.4.1)
57
69
  racc
58
- pry (0.15.2)
70
+ pp (0.6.3)
71
+ prettyprint
72
+ prettyprint (0.2.0)
73
+ prism (1.9.0)
74
+ pry (0.16.0)
59
75
  coderay (~> 1.1)
60
76
  method_source (~> 1.0)
77
+ reline (>= 0.6.0)
78
+ psych (5.3.1)
79
+ date
80
+ stringio
61
81
  racc (1.8.1)
62
82
  rainbow (3.1.1)
63
- rake (13.2.1)
64
- regexp_parser (2.10.0)
65
- rspec (3.13.0)
83
+ rake (13.3.1)
84
+ rdoc (7.2.0)
85
+ erb
86
+ psych (>= 4.0.0)
87
+ tsort
88
+ regexp_parser (2.12.0)
89
+ reline (0.6.3)
90
+ io-console (~> 0.5)
91
+ rspec (3.13.2)
66
92
  rspec-core (~> 3.13.0)
67
93
  rspec-expectations (~> 3.13.0)
68
94
  rspec-mocks (~> 3.13.0)
69
- rspec-core (3.13.2)
95
+ rspec-core (3.13.6)
70
96
  rspec-support (~> 3.13.0)
71
- rspec-expectations (3.13.3)
97
+ rspec-expectations (3.13.5)
72
98
  diff-lcs (>= 1.2.0, < 2.0)
73
99
  rspec-support (~> 3.13.0)
74
- rspec-mocks (3.13.2)
100
+ rspec-mocks (3.13.8)
75
101
  diff-lcs (>= 1.2.0, < 2.0)
76
102
  rspec-support (~> 3.13.0)
77
- rspec-support (3.13.2)
78
- rubocop (1.71.2)
103
+ rspec-support (3.13.7)
104
+ rubocop (1.84.2)
79
105
  json (~> 2.3)
80
- language_server-protocol (>= 3.17.0)
106
+ language_server-protocol (~> 3.17.0.2)
107
+ lint_roller (~> 1.1.0)
81
108
  parallel (~> 1.10)
82
109
  parser (>= 3.3.0.2)
83
110
  rainbow (>= 2.2.2, < 4.0)
84
111
  regexp_parser (>= 2.9.3, < 3.0)
85
- rubocop-ast (>= 1.38.0, < 2.0)
112
+ rubocop-ast (>= 1.49.0, < 2.0)
86
113
  ruby-progressbar (~> 1.7)
87
114
  unicode-display_width (>= 2.4.0, < 4.0)
88
- rubocop-ast (1.38.0)
89
- parser (>= 3.3.1.0)
90
- rubocop-rake (0.6.0)
91
- rubocop (~> 1.0)
92
- rubocop-rspec (3.4.0)
93
- rubocop (~> 1.61)
115
+ rubocop-ast (1.49.1)
116
+ parser (>= 3.3.7.2)
117
+ prism (~> 1.7)
118
+ rubocop-performance (1.26.1)
119
+ lint_roller (~> 1.1)
120
+ rubocop (>= 1.75.0, < 2.0)
121
+ rubocop-ast (>= 1.47.1, < 2.0)
94
122
  ruby-progressbar (1.13.0)
95
123
  securerandom (0.4.1)
96
- timeout (0.4.3)
124
+ standard (1.54.0)
125
+ language_server-protocol (~> 3.17.0.2)
126
+ lint_roller (~> 1.0)
127
+ rubocop (~> 1.84.0)
128
+ standard-custom (~> 1.0.0)
129
+ standard-performance (~> 1.8)
130
+ standard-custom (1.0.2)
131
+ lint_roller (~> 1.0)
132
+ rubocop (~> 1.50)
133
+ standard-performance (1.9.0)
134
+ lint_roller (~> 1.1)
135
+ rubocop-performance (~> 1.26.0)
136
+ stringio (3.2.0)
137
+ timeout (0.6.1)
138
+ tsort (0.2.0)
97
139
  tzinfo (2.0.6)
98
140
  concurrent-ruby (~> 1.0)
99
- unicode-display_width (3.1.4)
100
- unicode-emoji (~> 4.0, >= 4.0.4)
101
- unicode-emoji (4.0.4)
102
- uri (1.0.2)
141
+ unicode-display_width (3.2.0)
142
+ unicode-emoji (~> 4.1)
143
+ unicode-emoji (4.2.0)
144
+ uri (1.1.1)
103
145
 
104
146
  PLATFORMS
105
147
  aarch64-linux-musl
@@ -112,14 +154,15 @@ PLATFORMS
112
154
 
113
155
  DEPENDENCIES
114
156
  graphql-pagination!
157
+ irb
115
158
  kaminari-activerecord
116
159
  kaminari-core
160
+ openssl
161
+ ostruct
117
162
  pry
118
163
  rake
119
164
  rspec
120
- rubocop
121
- rubocop-rake
122
- rubocop-rspec
165
+ standard
123
166
 
124
167
  BUNDLED WITH
125
- 2.6.3
168
+ 4.0.3
data/README.md CHANGED
@@ -16,6 +16,8 @@ Add `graphql-pagination` to your Gemfile, you can use `kaminari-activerecord` or
16
16
 
17
17
  ## Usage example
18
18
 
19
+ ### With Fields
20
+
19
21
  Use `collection_type` instead of `connection_type` to define your type:
20
22
 
21
23
  ```ruby
@@ -29,8 +31,55 @@ Use `collection_type` instead of `connection_type` to define your type:
29
31
  end
30
32
  ```
31
33
 
34
+ ### With Resolvers
35
+
36
+ You can also use `collection_type` with GraphQL resolvers:
37
+
38
+ ```ruby
39
+ module Resolvers
40
+ class FruitsResolver < GraphQL::Schema::Resolver
41
+ type Types::FruitType.collection_type, null: false
42
+
43
+ argument :page, Integer, required: false
44
+ argument :limit, Integer, required: false
45
+
46
+ def resolve(page: nil, limit: nil)
47
+ ::Fruit.page(page).per(limit)
48
+ end
49
+ end
50
+ end
51
+
52
+ # In your query type
53
+ field :fruits, resolver: Resolvers::FruitsResolver
54
+ ```
55
+
32
56
  Value returned by query resolver must be a kaminari object or implements its page scope methods (`current_page`, `limit_value`, `total_count`, `total_pages`).
33
57
 
58
+ ## Paginated Field Helper
59
+
60
+ For a less verbose way to define paginated fields, use the `paginated_field` helper:
61
+
62
+ ```ruby
63
+ paginated_field :fruits, Types::FruitType.collection_type, null: true
64
+
65
+ def fruits(page: nil, per: nil)
66
+ ::Fruit.page(page).per(per)
67
+ end
68
+ ```
69
+
70
+ This automatically adds `page` and `per` arguments (both optional) to the field. You can also add additional arguments using a block:
71
+
72
+ ```ruby
73
+ paginated_field :fruits, Types::FruitType.collection_type, null: true do
74
+ argument :where, String, required: false
75
+ argument :order, String, required: false
76
+ end
77
+
78
+ def fruits(page: nil, per: nil, where: nil, order: nil)
79
+ ::Fruit.page(page).per(per)
80
+ end
81
+ ```
82
+
34
83
  ## GraphQL query
35
84
 
36
85
  ```graphql
@@ -117,6 +166,56 @@ end
117
166
  field :fruits, Types::FruitType.collection_type(metadata_type: MyMetadataType)
118
167
  ```
119
168
 
169
+ ## Complexity Calculation
170
+
171
+ To prevent loading too much data, GraphQL supports complexity calculation. This gem provides the `GraphqlPagination::CollectionField` module that can be prepended to your base field class to automatically calculate complexity for collection type fields.
172
+
173
+ The complexity calculation takes into account:
174
+ - The page size (from `limit` or `per` argument)
175
+ - Metadata fields requested
176
+ - Collection fields requested
177
+ - Nested fields within collection items
178
+
179
+ ### Usage
180
+
181
+ First, create a base field class and prepend the `GraphqlPagination::CollectionField` module:
182
+
183
+ ```ruby
184
+ class Types::BaseField < GraphQL::Schema::Field
185
+ prepend GraphqlPagination::CollectionField
186
+ end
187
+ ```
188
+
189
+ Then configure your base object to use this field class:
190
+
191
+ ```ruby
192
+ class Types::BaseObject < GraphQL::Schema::Object
193
+ field_class Types::BaseField
194
+ end
195
+ ```
196
+
197
+ Now all fields that return collection types will automatically have complexity calculation:
198
+
199
+ ```ruby
200
+ class Types::QueryType < Types::BaseObject
201
+ field :fruits, Types::FruitType.collection_type, null: true do
202
+ argument :page, Integer, required: false
203
+ argument :limit, Integer, required: false
204
+ end
205
+
206
+ def fruits(page: nil, limit: nil)
207
+ ::Fruit.page(page).per(limit)
208
+ end
209
+ end
210
+ ```
211
+
212
+ The complexity will be calculated as:
213
+ ```
214
+ 1 (field itself) + (page_size * items_complexity) + metadata_complexity + collection_complexity
215
+ ```
216
+
217
+ If no `limit` or `per` argument is provided, it will use the schema's default page size or fall back to 25 (Kaminari's default).
218
+
120
219
  ## Contributing
121
220
 
122
221
  Bug reports and pull requests are welcome on GitHub at https://github.com/renofi/graphql-pagination. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/Rakefile CHANGED
@@ -1,9 +1,8 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
- require 'rubocop/rake_task'
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "standard/rake"
4
4
 
5
5
  RSpec::Core::RakeTask.new(:spec)
6
- RuboCop::RakeTask.new
7
6
 
8
- task ci: %i[spec rubocop]
9
- task default: %i[spec rubocop:autocorrect_all]
7
+ task ci: %i[spec standard]
8
+ task default: %i[spec standard:fix]
@@ -0,0 +1,116 @@
1
+ # Complexity Calculation Example
2
+ #
3
+ # This example demonstrates how to use the CollectionField module
4
+ # to automatically calculate complexity for collection type fields.
5
+
6
+ require "bundler/setup"
7
+ require "graphql-pagination"
8
+ require "kaminari/core"
9
+
10
+ # Sample data model
11
+ class User
12
+ attr_reader :id, :name
13
+
14
+ def initialize(id, name)
15
+ @id = id
16
+ @name = name
17
+ end
18
+
19
+ def self.all
20
+ users = (1..100).map { |i| User.new(i, "User #{i}") }
21
+ Kaminari.paginate_array(users)
22
+ end
23
+ end
24
+
25
+ # GraphQL Types
26
+ class UserType < GraphQL::Schema::Object
27
+ field :id, ID, null: false
28
+ field :name, String, null: false
29
+ end
30
+
31
+ # Base field with complexity calculation
32
+ class BaseField < GraphQL::Schema::Field
33
+ prepend GraphqlPagination::CollectionField
34
+ end
35
+
36
+ class BaseObject < GraphQL::Schema::Object
37
+ field_class BaseField
38
+ end
39
+
40
+ class QueryType < BaseObject
41
+ field :users, UserType.collection_type, null: false do
42
+ argument :page, Integer, required: false
43
+ argument :limit, Integer, required: false
44
+ end
45
+
46
+ def users(page: nil, limit: nil)
47
+ User.all.page(page).per(limit)
48
+ end
49
+ end
50
+
51
+ class ExampleSchema < GraphQL::Schema
52
+ query QueryType
53
+ max_complexity 500
54
+ end
55
+
56
+ # Example queries
57
+ simple_query = <<~GRAPHQL
58
+ {
59
+ users(limit: 5) {
60
+ collection {
61
+ id
62
+ name
63
+ }
64
+ metadata {
65
+ currentPage
66
+ totalPages
67
+ }
68
+ }
69
+ }
70
+ GRAPHQL
71
+
72
+ complex_query = <<~GRAPHQL
73
+ {
74
+ users(limit: 50) {
75
+ collection {
76
+ id
77
+ name
78
+ }
79
+ metadata {
80
+ currentPage
81
+ totalPages
82
+ totalCount
83
+ limitValue
84
+ }
85
+ }
86
+ }
87
+ GRAPHQL
88
+
89
+ puts "Example 1: Simple query with limit: 5"
90
+ puts "=" * 50
91
+ result = ExampleSchema.execute(simple_query)
92
+ if result["errors"]
93
+ puts "Errors: #{result["errors"]}"
94
+ else
95
+ puts "Success! Retrieved #{result["data"]["users"]["collection"].size} users"
96
+ puts "Current Page: #{result["data"]["users"]["metadata"]["currentPage"]}"
97
+ puts "Total Pages: #{result["data"]["users"]["metadata"]["totalPages"]}"
98
+ end
99
+
100
+ puts "\n"
101
+ puts "Example 2: Complex query with limit: 50"
102
+ puts "=" * 50
103
+ result = ExampleSchema.execute(complex_query)
104
+ if result["errors"]
105
+ puts "Errors: #{result["errors"]}"
106
+ else
107
+ puts "Success! Retrieved #{result["data"]["users"]["collection"].size} users"
108
+ puts "Current Page: #{result["data"]["users"]["metadata"]["currentPage"]}"
109
+ puts "Total Pages: #{result["data"]["users"]["metadata"]["totalPages"]}"
110
+ puts "Total Count: #{result["data"]["users"]["metadata"]["totalCount"]}"
111
+ puts "Limit Value: #{result["data"]["users"]["metadata"]["limitValue"]}"
112
+ end
113
+
114
+ puts "\n"
115
+ puts "Note: With the CollectionField module, complexity is automatically calculated"
116
+ puts "based on the limit argument, preventing queries from loading too much data."
@@ -1,30 +1,30 @@
1
- lib = File.expand_path('lib', __dir__)
1
+ lib = File.expand_path("lib", __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'graphql_pagination/version'
3
+ require "graphql_pagination/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = 'graphql-pagination'
6
+ spec.name = "graphql-pagination"
7
7
  spec.version = GraphqlPagination::VERSION
8
- spec.authors = ['Krzysztof Knapik', 'RenoFi Engineering Team']
9
- spec.email = ['knapo@knapo.net', 'engineering@renofi.com']
8
+ spec.authors = ["Krzysztof Knapik", "RenoFi Engineering Team"]
9
+ spec.email = ["knapo@knapo.net", "engineering@renofi.com"]
10
10
 
11
- spec.summary = 'Page-based kaminari pagination for graphql.'
12
- spec.description = 'Page-based kaminari pagination for graphql returning collection and pagination metadata.'
13
- spec.homepage = 'https://github.com/RenoFi/graphql-pagination'
14
- spec.license = 'MIT'
11
+ spec.summary = "Page-based kaminari pagination for graphql."
12
+ spec.description = "Page-based kaminari pagination for graphql returning collection and pagination metadata."
13
+ spec.homepage = "https://github.com/RenoFi/graphql-pagination"
14
+ spec.license = "MIT"
15
15
 
16
- spec.metadata['homepage_uri'] = 'https://github.com/RenoFi/graphql-pagination'
17
- spec.metadata['source_code_uri'] = 'https://github.com/RenoFi/graphql-pagination'
18
- spec.metadata['rubygems_mfa_required'] = 'true'
16
+ spec.metadata["homepage_uri"] = "https://github.com/RenoFi/graphql-pagination"
17
+ spec.metadata["source_code_uri"] = "https://github.com/RenoFi/graphql-pagination"
18
+ spec.metadata["rubygems_mfa_required"] = "true"
19
19
 
20
- spec.required_ruby_version = Gem::Requirement.new('>= 3.3.0')
20
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.4.0")
21
21
 
22
22
  spec.files = Dir.chdir(__dir__) do
23
23
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(bin/|spec/|\.rub)}) }
24
24
  end
25
- spec.bindir = 'exe'
25
+ spec.bindir = "exe"
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
- spec.require_paths = ['lib']
27
+ spec.require_paths = ["lib"]
28
28
 
29
- spec.add_dependency 'graphql', '>= 2.4.7'
29
+ spec.add_dependency "graphql", ">= 2.4.7"
30
30
  end
@@ -1 +1 @@
1
- require 'graphql_pagination'
1
+ require "graphql_pagination"
@@ -0,0 +1,60 @@
1
+ module GraphqlPagination
2
+ module CollectionField
3
+ # Check if the field returns a collection type
4
+ def collection_type?
5
+ if @return_type_expr.respond_to?(:graphql_name)
6
+ @return_type_expr.graphql_name.end_with?("Collection")
7
+ else
8
+ false
9
+ end
10
+ end
11
+
12
+ # Calculate complexity for collection fields
13
+ # This is based on graphql-ruby's connection complexity calculation
14
+ # See: https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/schema/field.rb#L472
15
+ def calculate_complexity(query:, nodes:, child_complexity:)
16
+ if collection_type?
17
+ arguments = query.arguments_for(nodes.first, self)
18
+
19
+ # Get the page size from the `limit` or `per` argument
20
+ # Default to a reasonable value if not provided
21
+ max_possible_page_size = arguments[:limit] || arguments[:per]
22
+
23
+ if max_possible_page_size.nil?
24
+ # Use schema defaults or a reasonable default
25
+ # Note: default_page_size, max_page_size are GraphQL::Schema::Field methods
26
+ # query.schema.default_page_size and query.schema.default_max_page_size are schema-level configs
27
+ max_possible_page_size = default_page_size ||
28
+ query.schema.default_page_size ||
29
+ max_page_size ||
30
+ query.schema.default_max_page_size ||
31
+ 25 # Reasonable default for kaminari
32
+ end
33
+
34
+ metadata_complexity = 0
35
+ lookahead = GraphQL::Execution::Lookahead.new(query:, field: self, ast_nodes: nodes, owner_type: owner)
36
+
37
+ # Calculate metadata complexity
38
+ if (metadata_lookahead = lookahead.selection(:metadata)).selected?
39
+ metadata_complexity += 1 # metadata field itself
40
+ metadata_complexity += metadata_lookahead.selections.size # metadata subfields
41
+ end
42
+
43
+ # Check for total_pages and total_count (they are part of metadata)
44
+ # Note: These are already counted above if metadata is selected
45
+
46
+ nodes_edges_complexity = 0
47
+ nodes_edges_complexity += 1 if lookahead.selects?(:collection)
48
+
49
+ # Calculate items complexity
50
+ # Subtract metadata and collection field complexity from child complexity
51
+ items_complexity = child_complexity - metadata_complexity - nodes_edges_complexity
52
+
53
+ # Apply complexity: 1 (this field) + (page_size * items) + metadata + collection
54
+ 1 + (max_possible_page_size * items_complexity) + metadata_complexity + nodes_edges_complexity
55
+ else
56
+ super
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,11 @@
1
+ module GraphqlPagination
2
+ module PaginatedField
3
+ def paginated_field(name, type, **, &)
4
+ field(name, type, **) do
5
+ argument :page, Integer, required: false
6
+ argument :per, Integer, required: false
7
+ instance_eval(&) if block_given?
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module GraphqlPagination
2
- VERSION = '2.4.0'.freeze
2
+ VERSION = "2.5.0".freeze
3
3
  end
@@ -1,12 +1,16 @@
1
- require 'graphql_pagination/version'
2
- require 'graphql'
3
- require 'graphql/schema'
1
+ require "graphql_pagination/version"
2
+ require "graphql"
3
+ require "graphql/schema"
4
4
 
5
5
  module GraphqlPagination
6
6
  end
7
7
 
8
- require 'graphql_pagination/collection_base_error'
9
- require 'graphql_pagination/collection_type'
10
- require 'graphql_pagination/collection_metadata_type'
8
+ require "graphql_pagination/collection_base_error"
9
+ require "graphql_pagination/collection_type"
10
+ require "graphql_pagination/collection_metadata_type"
11
+ require "graphql_pagination/collection_field"
12
+ require "graphql_pagination/paginated_field"
11
13
 
12
14
  GraphQL::Schema::Object.extend GraphqlPagination::CollectionType
15
+ GraphQL::Schema::Resolver.extend GraphqlPagination::CollectionType
16
+ GraphQL::Schema::Object.extend GraphqlPagination::PaginatedField
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-pagination
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Knapik
8
8
  - RenoFi Engineering Team
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-02-05 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -50,12 +50,15 @@ files:
50
50
  - LICENSE
51
51
  - README.md
52
52
  - Rakefile
53
+ - examples/complexity_example.rb
53
54
  - graphql-pagination.gemspec
54
55
  - lib/graphql-pagination.rb
55
56
  - lib/graphql_pagination.rb
56
57
  - lib/graphql_pagination/collection_base_error.rb
58
+ - lib/graphql_pagination/collection_field.rb
57
59
  - lib/graphql_pagination/collection_metadata_type.rb
58
60
  - lib/graphql_pagination/collection_type.rb
61
+ - lib/graphql_pagination/paginated_field.rb
59
62
  - lib/graphql_pagination/version.rb
60
63
  homepage: https://github.com/RenoFi/graphql-pagination
61
64
  licenses:
@@ -71,14 +74,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
74
  requirements:
72
75
  - - ">="
73
76
  - !ruby/object:Gem::Version
74
- version: 3.3.0
77
+ version: 3.4.0
75
78
  required_rubygems_version: !ruby/object:Gem::Requirement
76
79
  requirements:
77
80
  - - ">="
78
81
  - !ruby/object:Gem::Version
79
82
  version: '0'
80
83
  requirements: []
81
- rubygems_version: 3.6.3
84
+ rubygems_version: 4.0.9
82
85
  specification_version: 4
83
86
  summary: Page-based kaminari pagination for graphql.
84
87
  test_files: []