graphiti 1.3.9 → 1.7.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/probots.yml +2 -0
- data/.github/workflows/ci.yml +26 -8
- data/.github/workflows/release.yml +36 -0
- data/.gitignore +1 -0
- data/.standard.yml +1 -1
- data/Appraisals +15 -0
- data/CHANGELOG.md +119 -1
- data/Gemfile +1 -0
- data/README.md +2 -1
- data/gemfiles/rails_7_1.gemfile +18 -0
- data/gemfiles/rails_7_1_graphiti_rails.gemfile +19 -0
- data/graphiti.gemspec +1 -1
- data/lib/graphiti/adapters/abstract.rb +1 -1
- data/lib/graphiti/adapters/active_record.rb +7 -1
- data/lib/graphiti/configuration.rb +13 -0
- data/lib/graphiti/debugger.rb +27 -5
- data/lib/graphiti/query.rb +22 -3
- data/lib/graphiti/renderer.rb +8 -1
- data/lib/graphiti/resource/dsl.rb +1 -1
- data/lib/graphiti/resource/interface.rb +19 -6
- data/lib/graphiti/resource/links.rb +1 -1
- data/lib/graphiti/resource/sideloading.rb +2 -2
- data/lib/graphiti/resource_proxy.rb +35 -5
- data/lib/graphiti/runner.rb +3 -1
- data/lib/graphiti/schema.rb +1 -1
- data/lib/graphiti/scope.rb +61 -2
- data/lib/graphiti/scoping/filter.rb +3 -3
- data/lib/graphiti/serializer.rb +3 -3
- data/lib/graphiti/sideload/polymorphic_belongs_to.rb +1 -1
- data/lib/graphiti/sideload.rb +10 -3
- data/lib/graphiti/util/cache_debug.rb +88 -0
- data/lib/graphiti/util/link.rb +1 -0
- data/lib/graphiti/util/serializer_relationships.rb +1 -1
- data/lib/graphiti/version.rb +1 -1
- data/lib/graphiti.rb +22 -3
- data/package.json +111 -0
- metadata +14 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 526bde7653f2c482b92ee75c5a7afee5823f675024b9c6925e86aa04924e27d3
|
4
|
+
data.tar.gz: e7441df1db552bf0b30ee3d85a16fa644f4d770cff40bf199e9338c003ce810b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cccf050029f667eb96d0c76e379df5ecaddec574eede0708b3847cdb821b35fd1b527a8ffc5759d72f9d9a0f739d1d756cc4ea114dad1606621f6de13a814e3
|
7
|
+
data.tar.gz: 2f80a0ce18045b984ec722a395f79028ae1da6d2fbd7923424d5371bf177990c3692fa7c835d5ad27ecfe56b9d0da0a215c7ae3aff82cf47fc9822fb9e88a6c5
|
data/.github/probots.yml
ADDED
data/.github/workflows/ci.yml
CHANGED
@@ -28,10 +28,11 @@ jobs:
|
|
28
28
|
fail-fast: false
|
29
29
|
matrix:
|
30
30
|
ruby:
|
31
|
-
- "2.6"
|
32
31
|
- "2.7"
|
33
32
|
- "3.0"
|
34
33
|
- "3.1"
|
34
|
+
- "3.2"
|
35
|
+
- "3.3"
|
35
36
|
gemfile:
|
36
37
|
- Gemfile
|
37
38
|
- gemfiles/rails_5_2.gemfile
|
@@ -40,12 +41,13 @@ jobs:
|
|
40
41
|
- gemfiles/rails_5_2_graphiti_rails.gemfile
|
41
42
|
- gemfiles/rails_6_graphiti_rails.gemfile
|
42
43
|
- gemfiles/rails_7_graphiti_rails.gemfile
|
44
|
+
- gemfiles/rails_7_1_graphiti_rails.gemfile
|
43
45
|
appraisal:
|
44
46
|
- true
|
45
47
|
- false
|
46
48
|
include:
|
47
49
|
- ruby: ruby-head
|
48
|
-
gemfile:
|
50
|
+
gemfile: gemfiles/rails_7_1.gemfile
|
49
51
|
appraisal: true
|
50
52
|
- ruby: ruby-head
|
51
53
|
gemfile: Gemfile
|
@@ -66,7 +68,9 @@ jobs:
|
|
66
68
|
appraisal: false
|
67
69
|
- gemfile: gemfiles/rails_7_graphiti_rails.gemfile
|
68
70
|
appraisal: false
|
69
|
-
|
71
|
+
- gemfile: gemfiles/rails_7_1_graphiti_rails.gemfile
|
72
|
+
appraisal: false
|
73
|
+
# Rails 5 can't run on Ruby 3
|
70
74
|
- gemfile: gemfiles/rails_5_2.gemfile
|
71
75
|
ruby: 3.0
|
72
76
|
- gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
|
@@ -75,11 +79,14 @@ jobs:
|
|
75
79
|
ruby: 3.1
|
76
80
|
- gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
|
77
81
|
ruby: 3.1
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
82
|
+
- gemfile: gemfiles/rails_5_2.gemfile
|
83
|
+
ruby: 3.2
|
84
|
+
- gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
|
85
|
+
ruby: 3.2
|
86
|
+
- gemfile: gemfiles/rails_5_2.gemfile
|
87
|
+
ruby: 3.3
|
88
|
+
- gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
|
89
|
+
ruby: 3.3
|
83
90
|
continue-on-error: ${{ matrix.ruby == 'ruby-head' }}
|
84
91
|
env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
|
85
92
|
BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}
|
@@ -94,3 +101,14 @@ jobs:
|
|
94
101
|
bundler-cache: true
|
95
102
|
- name: Run tests
|
96
103
|
run: bundle exec rspec
|
104
|
+
publish:
|
105
|
+
name: Release
|
106
|
+
runs-on: ubuntu-latest
|
107
|
+
if: github.ref == 'refs/heads/master'
|
108
|
+
needs: [test]
|
109
|
+
steps:
|
110
|
+
- name: Dispatch Release
|
111
|
+
uses: benc-uk/workflow-dispatch@v1
|
112
|
+
with:
|
113
|
+
workflow: Generate New Release
|
114
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
name: Generate New Release
|
3
|
+
|
4
|
+
on:
|
5
|
+
workflow_dispatch:
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
release:
|
9
|
+
name: Release
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
steps:
|
12
|
+
- name: Checkout
|
13
|
+
uses: actions/checkout@v3
|
14
|
+
with:
|
15
|
+
submodules: true
|
16
|
+
persist-credentials: false
|
17
|
+
- name: Set up Ruby
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: "3.1"
|
21
|
+
- name: Build
|
22
|
+
run: |
|
23
|
+
gem install bundler
|
24
|
+
git submodule update --init --recursive
|
25
|
+
bundle install --jobs 4 --retry 3
|
26
|
+
- name: Setup Node.js
|
27
|
+
uses: actions/setup-node@v2
|
28
|
+
with:
|
29
|
+
node-version: 14
|
30
|
+
- name: Install Dependencies
|
31
|
+
run: yarn install --frozen-lockfile
|
32
|
+
- name: Release
|
33
|
+
env:
|
34
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
35
|
+
GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
|
36
|
+
run: node_modules/.bin/semantic-release
|
data/.gitignore
CHANGED
data/.standard.yml
CHANGED
data/Appraisals
CHANGED
@@ -42,3 +42,18 @@ appraise "rails-7-graphiti-rails" do
|
|
42
42
|
gem "database_cleaner"
|
43
43
|
gem "graphiti-rails", "~> 0.4.0"
|
44
44
|
end
|
45
|
+
|
46
|
+
appraise "rails-7-1" do
|
47
|
+
gem "rails", "~> 7.1"
|
48
|
+
gem "rspec-rails"
|
49
|
+
gem "sqlite3", "~> 1.4.0"
|
50
|
+
gem "database_cleaner"
|
51
|
+
end
|
52
|
+
|
53
|
+
appraise "rails-7-1-graphiti-rails" do
|
54
|
+
gem "rails", "~> 7.1"
|
55
|
+
gem "rspec-rails"
|
56
|
+
gem "sqlite3", "~> 1.4.0"
|
57
|
+
gem "database_cleaner"
|
58
|
+
gem "graphiti-rails", "~> 0.4.0"
|
59
|
+
end
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,122 @@
|
|
1
|
-
|
1
|
+
graphiti changelog
|
2
|
+
|
3
|
+
## [1.7.5](https://github.com/graphiti-api/graphiti/compare/v1.7.4...v1.7.5) (2024-09-16)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* Fixes error in version check for ActiveRecord adapter introduced in [#478](https://github.com/graphiti-api/graphiti/issues/478) ([#479](https://github.com/graphiti-api/graphiti/issues/479)) ([42c82c3](https://github.com/graphiti-api/graphiti/commit/42c82c397f20eb91c02835e518ff4c351c028ea7))
|
9
|
+
|
10
|
+
## [1.7.4](https://github.com/graphiti-api/graphiti/compare/v1.7.3...v1.7.4) (2024-09-11)
|
11
|
+
|
12
|
+
|
13
|
+
### Bug Fixes
|
14
|
+
|
15
|
+
* update ActiveRecord adapter w/ support for Rails 7.2+ ([#478](https://github.com/graphiti-api/graphiti/issues/478)) ([8313e33](https://github.com/graphiti-api/graphiti/commit/8313e3359f0dde28d9940867c7ded964db4c854d))
|
16
|
+
|
17
|
+
## [1.7.3](https://github.com/graphiti-api/graphiti/compare/v1.7.2...v1.7.3) (2024-06-26)
|
18
|
+
|
19
|
+
|
20
|
+
### Bug Fixes
|
21
|
+
|
22
|
+
* require OpenStruct explicitly ([#475](https://github.com/graphiti-api/graphiti/issues/475)) ([e0fa18a](https://github.com/graphiti-api/graphiti/commit/e0fa18a8d7f051e385e6e081f79f2ecae92a9260))
|
23
|
+
|
24
|
+
## [1.7.2](https://github.com/graphiti-api/graphiti/compare/v1.7.1...v1.7.2) (2024-06-11)
|
25
|
+
|
26
|
+
|
27
|
+
### Bug Fixes
|
28
|
+
|
29
|
+
* require necessary ActiveSupport parts in proper order ([bb2a488](https://github.com/graphiti-api/graphiti/commit/bb2a48874a6533522df6eb027d0df8ec14c80a20))
|
30
|
+
|
31
|
+
## [1.7.1](https://github.com/graphiti-api/graphiti/compare/v1.7.0...v1.7.1) (2024-04-18)
|
32
|
+
|
33
|
+
|
34
|
+
### Bug Fixes
|
35
|
+
|
36
|
+
* properly display .find vs .all in debugger statements ([d2a7a03](https://github.com/graphiti-api/graphiti/commit/d2a7a038a649818979d52ccd898e68dba78b051f))
|
37
|
+
* rescue error from sideloads updated_at calculation, defaulting to the current time ([661e3b5](https://github.com/graphiti-api/graphiti/commit/661e3b5212e2649870a200067d0d5d52fa962637))
|
38
|
+
|
39
|
+
# [1.7.0](https://github.com/graphiti-api/graphiti/compare/v1.6.4...v1.7.0) (2024-03-27)
|
40
|
+
|
41
|
+
|
42
|
+
### Features
|
43
|
+
|
44
|
+
* Add support for caching renders in Graphiti, and better support using etags and stale? in the controller ([#424](https://github.com/graphiti-api/graphiti/issues/424)) ([8bae50a](https://github.com/graphiti-api/graphiti/commit/8bae50ab82559e2644d506e16a4f715effd89317))
|
45
|
+
|
46
|
+
## [1.6.4](https://github.com/graphiti-api/graphiti/compare/v1.6.3...v1.6.4) (2024-03-27)
|
47
|
+
|
48
|
+
## [1.6.3](https://github.com/graphiti-api/graphiti/compare/v1.6.2...v1.6.3) (2024-03-26)
|
49
|
+
|
50
|
+
|
51
|
+
### Bug Fixes
|
52
|
+
|
53
|
+
* Remove thread pool executor logic until we get a better handle on what's causing thread pool hangs. refs [#469](https://github.com/graphiti-api/graphiti/issues/469) ([7941b6f](https://github.com/graphiti-api/graphiti/commit/7941b6f75ce1001b034ed6e83c148b893e9f3d99)), closes [#471](https://github.com/graphiti-api/graphiti/issues/471) [#470](https://github.com/graphiti-api/graphiti/issues/470)
|
54
|
+
|
55
|
+
## [1.6.2](https://github.com/graphiti-api/graphiti/compare/v1.6.1...v1.6.2) (2024-03-22)
|
56
|
+
|
57
|
+
|
58
|
+
### Bug Fixes
|
59
|
+
|
60
|
+
* thread pool scope and mutex need to be global across all instances of Scope for it to be a global thread pool ([#471](https://github.com/graphiti-api/graphiti/issues/471)) ([51fb51c](https://github.com/graphiti-api/graphiti/commit/51fb51c31f0043d98aa07f689a8cf8c758fa823b))
|
61
|
+
|
62
|
+
## [1.6.1](https://github.com/graphiti-api/graphiti/compare/v1.6.0...v1.6.1) (2024-03-22)
|
63
|
+
|
64
|
+
|
65
|
+
### Bug Fixes
|
66
|
+
|
67
|
+
* correct thread-pool mutex logic which was causing a deadlock ([0400ab0](https://github.com/graphiti-api/graphiti/commit/0400ab0d97a1382b66b5295fdc7aa7db680e77cc))
|
68
|
+
|
69
|
+
# [1.6.0](https://github.com/graphiti-api/graphiti/compare/v1.5.3...v1.6.0) (2024-03-20)
|
70
|
+
|
71
|
+
|
72
|
+
### Features
|
73
|
+
|
74
|
+
* add thread pool and concurrency_max_threads configuration option ([#470](https://github.com/graphiti-api/graphiti/issues/470)) ([697d761](https://github.com/graphiti-api/graphiti/commit/697d76172adec24cd7e7522300c8335233fdcc36))
|
75
|
+
|
76
|
+
## [1.5.3](https://github.com/graphiti-api/graphiti/compare/v1.5.2...v1.5.3) (2024-03-18)
|
77
|
+
|
78
|
+
|
79
|
+
### Bug Fixes
|
80
|
+
|
81
|
+
* leverage ruby-2.7 parameter forwarding ([#431](https://github.com/graphiti-api/graphiti/issues/431)) ([ae09a46](https://github.com/graphiti-api/graphiti/commit/ae09a464b2156742bb093537deac0578a1a3e40e))
|
82
|
+
* prevent :id stripping when :id not in path ([#447](https://github.com/graphiti-api/graphiti/issues/447)) ([e1dd811](https://github.com/graphiti-api/graphiti/commit/e1dd811283f6e6fe7a36b925934df0ecbb4d3411))
|
83
|
+
|
84
|
+
## [1.5.2](https://github.com/graphiti-api/graphiti/compare/v1.5.1...v1.5.2) (2024-03-18)
|
85
|
+
|
86
|
+
|
87
|
+
### Bug Fixes
|
88
|
+
|
89
|
+
* Enum should allow the conventionally case-sensitive operators ([#434](https://github.com/graphiti-api/graphiti/issues/434)) ([56d34fd](https://github.com/graphiti-api/graphiti/commit/56d34fd4801bc32c13d64aca880b82b717b2ab81))
|
90
|
+
|
91
|
+
## [1.5.1](https://github.com/graphiti-api/graphiti/compare/v1.5.0...v1.5.1) (2024-03-18)
|
92
|
+
|
93
|
+
|
94
|
+
### Bug Fixes
|
95
|
+
|
96
|
+
* polymorphic `on` expects a symbol ([#433](https://github.com/graphiti-api/graphiti/issues/433)) ([4e58702](https://github.com/graphiti-api/graphiti/commit/4e587021265323bd0b170b57e9c7aecaa7f826d7))
|
97
|
+
|
98
|
+
# [1.5.0](https://github.com/graphiti-api/graphiti/compare/v1.4.0...v1.5.0) (2024-03-18)
|
99
|
+
|
100
|
+
|
101
|
+
### Features
|
102
|
+
|
103
|
+
* add before_sideload hook ([#371](https://github.com/graphiti-api/graphiti/issues/371)) ([f68b61f](https://github.com/graphiti-api/graphiti/commit/f68b61ff09ec61ecf23acc5bc37d0accba14aeed))
|
104
|
+
|
105
|
+
## 1.4.0, Sun March 17th 2024
|
106
|
+
Features:
|
107
|
+
- [461](https://github.com/graphiti-api/graphiti/pull/461), [463](https://github.com/graphiti-api/graphiti/pull/463) Add support for Rails 7.1 + Ruby 3.2 + Ruby 3.3
|
108
|
+
|
109
|
+
Fixes:
|
110
|
+
- [464](https://github.com/graphiti-api/graphiti/pull/464) Check for url presence before trying to append
|
111
|
+
- [407](https://github.com/graphiti-api/graphiti/pull/407) Sort types in generated schema
|
112
|
+
- [421](https://github.com/graphiti-api/graphiti/pull/421) Re-use resource class for remote sideloads to avoid memory leak
|
113
|
+
- [452](https://github.com/graphiti-api/graphiti/pull/452) Resolve inconsistency for filters containing curly brackets
|
114
|
+
- [446](https://github.com/graphiti-api/graphiti/pull/446) Fix private call
|
115
|
+
|
116
|
+
## 1.3.9, May 25th 2022
|
117
|
+
Use an options hash for log subscriber instead of positional arguments
|
118
|
+
|
119
|
+
## 1.x ??
|
2
120
|
|
3
121
|
Features:
|
4
122
|
- [329](https://github.com/graphiti-api/graphiti/pull/329) Propagate `extra_fields` to related resource links.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
![
|
1
|
+
[![CI](https://github.com/graphiti-api/graphiti/actions/workflows/ci.yml/badge.svg)](https://github.com/graphiti-api/graphiti/actions/workflows/ci.yml)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/graphiti.svg)](https://badge.fury.io/rb/graphiti)
|
3
3
|
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
|
4
|
+
[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
|
4
5
|
|
5
6
|
<p align="center">
|
6
7
|
<a href="https://www.graphiti.dev/guides">
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 7.1"
|
6
|
+
gem "rspec-rails"
|
7
|
+
gem "sqlite3", "~> 1.4.0"
|
8
|
+
gem "database_cleaner"
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem "pry"
|
12
|
+
gem "pry-byebug", platform: [:mri]
|
13
|
+
gem "appraisal"
|
14
|
+
gem "guard"
|
15
|
+
gem "guard-rspec"
|
16
|
+
end
|
17
|
+
|
18
|
+
gemspec path: "../"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 7.1"
|
6
|
+
gem "rspec-rails"
|
7
|
+
gem "sqlite3", "~> 1.4.0"
|
8
|
+
gem "database_cleaner"
|
9
|
+
gem "graphiti-rails", "~> 0.4.0"
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem "pry"
|
13
|
+
gem "pry-byebug", platform: [:mri]
|
14
|
+
gem "appraisal"
|
15
|
+
gem "guard"
|
16
|
+
gem "guard-rspec"
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec path: "../"
|
data/graphiti.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.bindir = "exe"
|
17
17
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
18
|
spec.require_paths = ["lib"]
|
19
|
-
spec.required_ruby_version = ">= 2.
|
19
|
+
spec.required_ruby_version = ">= 2.7"
|
20
20
|
|
21
21
|
spec.add_dependency "jsonapi-serializable", "~> 0.3.0"
|
22
22
|
spec.add_dependency "jsonapi-renderer", "~> 0.2", ">= 0.2.2"
|
@@ -26,6 +26,7 @@ module Graphiti
|
|
26
26
|
alias_method :filter_boolean_eq, :filter_eq
|
27
27
|
alias_method :filter_uuid_eq, :filter_eq
|
28
28
|
alias_method :filter_enum_eq, :filter_eq
|
29
|
+
alias_method :filter_enum_eql, :filter_eq
|
29
30
|
|
30
31
|
def filter_not_eq(scope, attribute, value)
|
31
32
|
scope.where.not(attribute => value)
|
@@ -37,6 +38,7 @@ module Graphiti
|
|
37
38
|
alias_method :filter_boolean_not_eq, :filter_not_eq
|
38
39
|
alias_method :filter_uuid_not_eq, :filter_not_eq
|
39
40
|
alias_method :filter_enum_not_eq, :filter_not_eq
|
41
|
+
alias_method :filter_enum_not_eql, :filter_not_eq
|
40
42
|
|
41
43
|
def filter_string_eq(scope, attribute, value, is_not: false)
|
42
44
|
column = column_for(scope, attribute)
|
@@ -302,7 +304,11 @@ module Graphiti
|
|
302
304
|
end
|
303
305
|
|
304
306
|
def close
|
305
|
-
::ActiveRecord
|
307
|
+
if ::ActiveRecord.version > "7.2"
|
308
|
+
::ActiveRecord::Base.connection_handler.clear_active_connections!
|
309
|
+
else
|
310
|
+
::ActiveRecord::Base.clear_active_connections!
|
311
|
+
end
|
306
312
|
end
|
307
313
|
|
308
314
|
def can_group?
|
@@ -15,10 +15,12 @@ module Graphiti
|
|
15
15
|
attr_accessor :pagination_links
|
16
16
|
attr_accessor :typecast_reads
|
17
17
|
attr_accessor :raise_on_missing_sidepost
|
18
|
+
attr_accessor :before_sideload
|
18
19
|
|
19
20
|
attr_reader :debug, :debug_models
|
20
21
|
|
21
22
|
attr_writer :schema_path
|
23
|
+
attr_writer :cache_rendering
|
22
24
|
|
23
25
|
# Set defaults
|
24
26
|
# @api private
|
@@ -31,6 +33,7 @@ module Graphiti
|
|
31
33
|
@pagination_links = false
|
32
34
|
@typecast_reads = true
|
33
35
|
@raise_on_missing_sidepost = true
|
36
|
+
@cache_rendering = false
|
34
37
|
self.debug = ENV.fetch("GRAPHITI_DEBUG", true)
|
35
38
|
self.debug_models = ENV.fetch("GRAPHITI_DEBUG_MODELS", false)
|
36
39
|
|
@@ -51,6 +54,16 @@ module Graphiti
|
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
57
|
+
def cache_rendering?
|
58
|
+
use_caching = @cache_rendering && Graphiti.cache.respond_to?(:fetch)
|
59
|
+
|
60
|
+
use_caching.tap do |use|
|
61
|
+
if @cache_rendering && !Graphiti.cache&.respond_to?(:fetch)
|
62
|
+
raise "You must configure a cache store in order to use cache_rendering. Set Graphiti.cache = Rails.cache, for example."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
54
67
|
def schema_path
|
55
68
|
@schema_path ||= raise("No schema_path defined! Set Graphiti.config.schema_path to save your schema.")
|
56
69
|
end
|
data/lib/graphiti/debugger.rb
CHANGED
@@ -36,7 +36,7 @@ module Graphiti
|
|
36
36
|
json[:sideload] = sideload.name
|
37
37
|
end
|
38
38
|
if params
|
39
|
-
query = "#{payload[:resource].class.name}
|
39
|
+
query = "#{payload[:resource].class.name}.#{payload[:action]}(#{JSON.pretty_generate(params)}).data"
|
40
40
|
logs << [query, :cyan, true]
|
41
41
|
logs << ["The error occurred when running the above query. Copy/paste it into a rake task or Rails console session to reproduce. Keep in mind you may have to set context.", :yellow, true]
|
42
42
|
else
|
@@ -64,7 +64,7 @@ module Graphiti
|
|
64
64
|
query = if sideload.class.scope_proc
|
65
65
|
"#{payload[:resource].class.name}: Manual sideload via .scope"
|
66
66
|
else
|
67
|
-
"#{payload[:resource].class.name}
|
67
|
+
"#{payload[:resource].class.name}.#{payload[:action]}(#{params.inspect})"
|
68
68
|
end
|
69
69
|
logs << [" #{query}", :cyan, true]
|
70
70
|
json[:query] = query
|
@@ -82,7 +82,7 @@ module Graphiti
|
|
82
82
|
title = "Top Level Data Retrieval (+ sideloads):"
|
83
83
|
logs << [title, :green, true]
|
84
84
|
json[:title] = title
|
85
|
-
query = "#{payload[:resource].class.name}
|
85
|
+
query = "#{payload[:resource].class.name}.#{payload[:action]}(#{params.inspect})"
|
86
86
|
logs << [query, :cyan, true]
|
87
87
|
json[:query] = query
|
88
88
|
logs << ["Returned Models: #{results}"] if debug_models
|
@@ -98,7 +98,30 @@ module Graphiti
|
|
98
98
|
took = ((stop - start) * 1000.0).round(2)
|
99
99
|
logs << [""]
|
100
100
|
logs << ["=== Graphiti Debug", :green, true]
|
101
|
-
|
101
|
+
if payload[:proxy]&.cached? && Graphiti.config.cache_rendering?
|
102
|
+
logs << ["Rendering (cached):", :green, true]
|
103
|
+
|
104
|
+
Graphiti::Util::CacheDebug.new(payload[:proxy]).analyze do |cache_debug|
|
105
|
+
logs << ["Cache key for #{cache_debug.name}", :blue, true]
|
106
|
+
logs << if cache_debug.volatile?
|
107
|
+
[" \\_ volatile | Request count: #{cache_debug.request_count} | Hit count: #{cache_debug.hit_count}", :red, true]
|
108
|
+
else
|
109
|
+
[" \\_ stable | Request count: #{cache_debug.request_count} | Hit count: #{cache_debug.hit_count}", :blue, true]
|
110
|
+
end
|
111
|
+
|
112
|
+
if cache_debug.changed_key?
|
113
|
+
logs << [" [x] cache key changed #{cache_debug.last_version[:etag]} -> #{cache_debug.current_version[:etag]}", :red]
|
114
|
+
logs << [" removed: #{cache_debug.removed_segments}", :red]
|
115
|
+
logs << [" added: #{cache_debug.added_segments}", :red]
|
116
|
+
elsif cache_debug.new_key?
|
117
|
+
logs << [" [+] cache key added #{cache_debug.current_version[:etag]}", :red, true]
|
118
|
+
else
|
119
|
+
logs << [" [✓] #{cache_debug.current_version[:etag]}", :green, true]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
else
|
123
|
+
logs << ["Rendering:", :green, true]
|
124
|
+
end
|
102
125
|
logs << ["Took: #{took}ms", :magenta, true]
|
103
126
|
end
|
104
127
|
end
|
@@ -140,7 +163,6 @@ module Graphiti
|
|
140
163
|
params ||= {}
|
141
164
|
params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
|
142
165
|
params.reject! { |k, v| [:controller, :action, :format, :debug].include?(k.to_sym) }
|
143
|
-
params.reject! { |k, v| k.to_sym == :include }
|
144
166
|
params.deep_symbolize_keys
|
145
167
|
end
|
146
168
|
|
data/lib/graphiti/query.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "digest"
|
2
|
+
|
1
3
|
module Graphiti
|
2
4
|
class Query
|
3
5
|
attr_reader :resource, :association_name, :params, :action
|
@@ -76,11 +78,14 @@ module Graphiti
|
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
81
|
+
class RemoteSideloadResource < ::Graphiti::Resource
|
82
|
+
self.remote = "_remote_sideload_".freeze
|
83
|
+
self.abstract_class = true # exclude from schema
|
84
|
+
end
|
85
|
+
|
79
86
|
def resource_for_sideload(sideload)
|
80
87
|
if @resource.remote?
|
81
|
-
|
82
|
-
self.remote = "_remote_sideload_"
|
83
|
-
}.new
|
88
|
+
RemoteSideloadResource.new
|
84
89
|
else
|
85
90
|
sideload.resource
|
86
91
|
end
|
@@ -229,8 +234,22 @@ module Graphiti
|
|
229
234
|
![false, "false"].include?(@params[:paginate])
|
230
235
|
end
|
231
236
|
|
237
|
+
def cache_key
|
238
|
+
"args-#{query_cache_key}"
|
239
|
+
end
|
240
|
+
|
232
241
|
private
|
233
242
|
|
243
|
+
def query_cache_key
|
244
|
+
attrs = {extra_fields: extra_fields,
|
245
|
+
fields: fields,
|
246
|
+
links: links?,
|
247
|
+
pagination_links: pagination_links?,
|
248
|
+
format: params[:format]}
|
249
|
+
|
250
|
+
Digest::SHA1.hexdigest(attrs.to_s)
|
251
|
+
end
|
252
|
+
|
234
253
|
def cast_page_param(name, value)
|
235
254
|
if [:before, :after].include?(name)
|
236
255
|
decode_cursor(value)
|
data/lib/graphiti/renderer.rb
CHANGED
@@ -68,7 +68,14 @@ module Graphiti
|
|
68
68
|
options[:meta][:debug] = Debugger.to_a if debug_json?
|
69
69
|
options[:proxy] = proxy
|
70
70
|
|
71
|
-
|
71
|
+
if proxy.cache? && Graphiti.config.cache_rendering?
|
72
|
+
Graphiti.cache.fetch("graphiti:render/#{proxy.cache_key}", version: proxy.updated_at, expires_in: proxy.cache_expires_in) do
|
73
|
+
options.delete(:cache) # ensure that we don't use JSONAPI-Resources's built-in caching logic
|
74
|
+
renderer.render(records, options)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
renderer.render(records, options)
|
78
|
+
end
|
72
79
|
end
|
73
80
|
end
|
74
81
|
|
@@ -4,8 +4,13 @@ module Graphiti
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
class_methods do
|
7
|
+
def cache_resource(expires_in: false)
|
8
|
+
@cache_resource = true
|
9
|
+
@cache_expires_in = expires_in
|
10
|
+
end
|
11
|
+
|
7
12
|
def all(params = {}, base_scope = nil)
|
8
|
-
|
13
|
+
validate_request!(params)
|
9
14
|
_all(params, {}, base_scope)
|
10
15
|
end
|
11
16
|
|
@@ -13,11 +18,11 @@ module Graphiti
|
|
13
18
|
def _all(params, opts, base_scope)
|
14
19
|
runner = Runner.new(self, params, opts.delete(:query), :all)
|
15
20
|
opts[:params] = params
|
16
|
-
runner.proxy(base_scope, opts)
|
21
|
+
runner.proxy(base_scope, opts.merge(caching_options))
|
17
22
|
end
|
18
23
|
|
19
24
|
def find(params = {}, base_scope = nil)
|
20
|
-
|
25
|
+
validate_request!(params)
|
21
26
|
_find(params, base_scope)
|
22
27
|
end
|
23
28
|
|
@@ -31,21 +36,29 @@ module Graphiti
|
|
31
36
|
params[:filter][:id] = id if id
|
32
37
|
|
33
38
|
runner = Runner.new(self, params, nil, :find)
|
34
|
-
|
39
|
+
|
40
|
+
find_options = {
|
35
41
|
single: true,
|
36
42
|
raise_on_missing: true,
|
37
43
|
bypass_required_filters: true
|
44
|
+
}.merge(caching_options)
|
45
|
+
|
46
|
+
runner.proxy base_scope, find_options
|
38
47
|
end
|
39
48
|
|
40
49
|
def build(params, base_scope = nil)
|
41
|
-
|
50
|
+
validate_request!(params)
|
42
51
|
runner = Runner.new(self, params)
|
43
52
|
runner.proxy(base_scope, single: true, raise_on_missing: true)
|
44
53
|
end
|
45
54
|
|
46
55
|
private
|
47
56
|
|
48
|
-
def
|
57
|
+
def caching_options
|
58
|
+
{cache: @cache_resource, cache_expires_in: @cache_expires_in}
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_request!(params)
|
49
62
|
return if Graphiti.context[:graphql] || !validate_endpoints?
|
50
63
|
|
51
64
|
if context&.respond_to?(:request)
|
@@ -76,7 +76,7 @@ module Graphiti
|
|
76
76
|
path = request_path
|
77
77
|
if [:update, :show, :destroy].include?(context_namespace) && has_id
|
78
78
|
path = request_path.split("/")
|
79
|
-
path.pop
|
79
|
+
path.pop if path.last == has_id.to_s
|
80
80
|
path = path.join("/")
|
81
81
|
end
|
82
82
|
e[:full_path].to_s == path && e[:actions].include?(context_namespace)
|
@@ -68,7 +68,7 @@ module Graphiti
|
|
68
68
|
model_ref = model
|
69
69
|
has_many name, opts do
|
70
70
|
params do |hash|
|
71
|
-
hash[:filter][:"#{as}_type"] = {
|
71
|
+
hash[:filter][:"#{as}_type"] = {eql: model_ref.name}
|
72
72
|
end
|
73
73
|
|
74
74
|
instance_eval(&blk) if blk
|
@@ -82,7 +82,7 @@ module Graphiti
|
|
82
82
|
model_ref = model
|
83
83
|
has_one name, opts do
|
84
84
|
params do |hash|
|
85
|
-
hash[:filter][:"#{as}_type"] = {
|
85
|
+
hash[:filter][:"#{as}_type"] = {eql: model_ref.name}
|
86
86
|
end
|
87
87
|
|
88
88
|
instance_eval(&blk) if blk
|