activeadmin-graphql 0.1.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 +7 -0
- data/CHANGELOG.md +6 -0
- data/CODE_OF_CONDUCT.md +31 -0
- data/CONTRIBUTING.md +27 -0
- data/LICENSE.md +21 -0
- data/README.md +49 -0
- data/activeadmin-graphql.gemspec +66 -0
- data/app/controllers/active_admin/graphql_controller.rb +168 -0
- data/docs/graphql-api.md +486 -0
- data/lib/active_admin/graphql/auth_context.rb +35 -0
- data/lib/active_admin/graphql/engine.rb +9 -0
- data/lib/active_admin/graphql/integration.rb +135 -0
- data/lib/active_admin/graphql/key_value_pair_input.rb +48 -0
- data/lib/active_admin/graphql/railtie.rb +10 -0
- data/lib/active_admin/graphql/record_source.rb +30 -0
- data/lib/active_admin/graphql/resource_config.rb +68 -0
- data/lib/active_admin/graphql/resource_definition_dsl.rb +117 -0
- data/lib/active_admin/graphql/resource_interface.rb +25 -0
- data/lib/active_admin/graphql/resource_query_proxy/controller.rb +149 -0
- data/lib/active_admin/graphql/resource_query_proxy.rb +112 -0
- data/lib/active_admin/graphql/run_action_mutation_config.rb +23 -0
- data/lib/active_admin/graphql/run_action_mutation_dsl.rb +32 -0
- data/lib/active_admin/graphql/run_action_payload.rb +27 -0
- data/lib/active_admin/graphql/schema_builder/build.rb +84 -0
- data/lib/active_admin/graphql/schema_builder/graph_params.rb +75 -0
- data/lib/active_admin/graphql/schema_builder/mutation_action_types.rb +52 -0
- data/lib/active_admin/graphql/schema_builder/mutation_batch.rb +61 -0
- data/lib/active_admin/graphql/schema_builder/mutation_collection.rb +118 -0
- data/lib/active_admin/graphql/schema_builder/mutation_create.rb +65 -0
- data/lib/active_admin/graphql/schema_builder/mutation_member.rb +122 -0
- data/lib/active_admin/graphql/schema_builder/mutation_type_builder.rb +52 -0
- data/lib/active_admin/graphql/schema_builder/mutation_update_destroy.rb +120 -0
- data/lib/active_admin/graphql/schema_builder/query_type.rb +53 -0
- data/lib/active_admin/graphql/schema_builder/query_type_collection.rb +84 -0
- data/lib/active_admin/graphql/schema_builder/query_type_member.rb +91 -0
- data/lib/active_admin/graphql/schema_builder/query_type_pages.rb +44 -0
- data/lib/active_admin/graphql/schema_builder/query_type_registered.rb +57 -0
- data/lib/active_admin/graphql/schema_builder/resolvers.rb +116 -0
- data/lib/active_admin/graphql/schema_builder/resources.rb +48 -0
- data/lib/active_admin/graphql/schema_builder/types_inputs.rb +119 -0
- data/lib/active_admin/graphql/schema_builder/types_object.rb +96 -0
- data/lib/active_admin/graphql/schema_builder/visibility.rb +58 -0
- data/lib/active_admin/graphql/schema_builder/wire.rb +36 -0
- data/lib/active_admin/graphql/schema_builder.rb +62 -0
- data/lib/active_admin/graphql/schema_field.rb +29 -0
- data/lib/active_admin/graphql/version.rb +7 -0
- data/lib/active_admin/graphql.rb +68 -0
- data/lib/active_admin/primary_key.rb +117 -0
- data/lib/activeadmin/graphql.rb +5 -0
- metadata +389 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7280a88a1db044b52f0b7d41ba523f165516d8dd11d7aab97f4f3ea857f1237b
|
|
4
|
+
data.tar.gz: 35cdf2b394b11536301ca4f405f794ad27e50a6d530386331a26a9a2748e2c7e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e363650ebc0646cb24e5fac85d954c175555e1f6a827c697a20d21e07bcb05fc60439d42a676f0987a3141fdd6fadd8e9fce17c2ba2b2308446f5b3b7c4e3c1c
|
|
7
|
+
data.tar.gz: 4fd30f0ae38793a83e9524429648e3c30d8b414ad9c2003ffed16680d39c21cab6505a13cd8fb17083b175f030fdfd5623e12b8af48c0814d77562cdcca88e8a
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
- Initial release: GraphQL API for ActiveAdmin extracted from the `activeadmin` fork, usable as `gem "activeadmin-graphql"` alongside `activeadmin` and `graphql`.
|
|
6
|
+
- Docs: full guide in [`docs/graphql-api.md`](docs/graphql-api.md), including a “Migrating GraphQL clients” section (enum names, typed CRUD inputs, `ActiveAdminKeyValuePair` lists). Links from an optional ActiveAdmin fork or doc site are mainly for discovery.
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We pledge to make participation in the activeadmin-graphql community a harassment-free experience for everyone. We operate on principles of mutual respect, privacy, and authentic engagement. We value substantive contributions and clarity on intentions.
|
|
6
|
+
|
|
7
|
+
## Our Standards
|
|
8
|
+
|
|
9
|
+
Examples of behavior that contributes to a positive environment include:
|
|
10
|
+
|
|
11
|
+
- Authenticity: Engaging with genuine curiosity and admitting uncertainty rather than feigning knowledge.
|
|
12
|
+
- Responsible innovation: Taking full responsibility for any content or code contributed, whether manually written or generated by automation tools.
|
|
13
|
+
- Gentle correction: Responding politely to errors. We view mistakes as opportunities for learning, provided they are addressed with humility.
|
|
14
|
+
- Inclusive language: Using language that welcomes diverse perspectives and respects the privacy and identity of all participants.
|
|
15
|
+
|
|
16
|
+
Examples of unacceptable behavior include:
|
|
17
|
+
|
|
18
|
+
- Harassment: Public or private harassment, trolling, or insulting comments.
|
|
19
|
+
- Weaponized complexity: Using jargon or overwhelming volume (including automated spam) to silence others.
|
|
20
|
+
- Publishing private information: Sharing others' data or personal context without explicit permission.
|
|
21
|
+
|
|
22
|
+
## Artificial Intelligence & Automation
|
|
23
|
+
|
|
24
|
+
In accordance with our commitment to collective awareness:
|
|
25
|
+
|
|
26
|
+
- Contributors are responsible for the accuracy and security of any AI-generated artifacts they submit.
|
|
27
|
+
- "The AI wrote it" is not a valid excuse for introducing bugs, security vulnerabilities, or bias.
|
|
28
|
+
|
|
29
|
+
## Enforcement
|
|
30
|
+
|
|
31
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@kiskolabs.com. All complaints will be reviewed and investigated promptly and fairly.
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Contributing Guidelines
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to activeadmin-graphql.
|
|
4
|
+
|
|
5
|
+
## How to Contribute
|
|
6
|
+
|
|
7
|
+
### 1. Reporting Issues
|
|
8
|
+
|
|
9
|
+
- Verify accuracy: Before posting, verify your information. Avoid generalizations.
|
|
10
|
+
- Use structured inputs: Provide clear goals, constraints, and reproduction steps.
|
|
11
|
+
|
|
12
|
+
### 2. Pull Request Process
|
|
13
|
+
|
|
14
|
+
- Scope: Keep PRs focused on a single goal.
|
|
15
|
+
- Context: Explain why the change is necessary.
|
|
16
|
+
- Testing: Run the RSpec suite (see the README for Appraisal and parallel test commands).
|
|
17
|
+
|
|
18
|
+
### 3. Review Process
|
|
19
|
+
|
|
20
|
+
- We encourage productive friction. Expect questions about your approach.
|
|
21
|
+
- If a reviewer suggests a change, view it as mutual aid, not criticism.
|
|
22
|
+
|
|
23
|
+
### Artificial Intelligence & Automation
|
|
24
|
+
|
|
25
|
+
1. You are the author: You act as the responsible agent for any code you submit. You must review, debug, and understand every line.
|
|
26
|
+
2. Manage cognitive load: Do not submit massive, unreviewed automated dumps.
|
|
27
|
+
3. Security: Never feed project secrets or private context into public AI models.
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrei Makarov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# activeadmin-graphql
|
|
2
|
+
|
|
3
|
+
GraphQL HTTP API for [ActiveAdmin](https://activeadmin.info), built with [graphql-ruby](https://graphql-ruby.org). Register resources as usual, optionally add a `graphql do ... end` block, enable the endpoint per namespace, and get a schema with queries and mutations aligned with ActiveAdmin authorization and filters.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
# Gemfile (graphql-ruby is pulled in by activeadmin-graphql)
|
|
9
|
+
gem "activeadmin"
|
|
10
|
+
gem "activeadmin-graphql"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
# config/initializers/active_admin.rb
|
|
15
|
+
ActiveAdmin.setup do |config|
|
|
16
|
+
config.namespace :admin do |admin|
|
|
17
|
+
admin.graphql = true
|
|
18
|
+
# admin.graphql_path = "graphql" # default: POST /admin/graphql
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Bundler loads this gem as usual; that requires `graphql-ruby` and wires ActiveAdmin routing and DSL for GraphQL.
|
|
24
|
+
|
|
25
|
+
Documentation: [docs/graphql-api.md](docs/graphql-api.md) covers the endpoint, schema, `graphql do … end`, authorization, composite PKs, visibility, and dataloaders. For an older GraphQL integration, see “Migrating GraphQL clients” in that guide (enum type names, typed mutation inputs, key/value lists vs JSON).
|
|
26
|
+
|
|
27
|
+
## Development
|
|
28
|
+
|
|
29
|
+
Tests use a minimal Rails app under `spec/dummy` with SQLite (`:memory:` in test; each [parallel_tests](https://github.com/grosser/parallel_tests) worker is a separate process with its own DB). From the gem root:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bundle install
|
|
33
|
+
bundle exec appraisal install # generates gemfiles/*.gemfile from Appraisals
|
|
34
|
+
bundle exec rubocop
|
|
35
|
+
bundle exec parallel_rspec spec # or: bundle exec rspec
|
|
36
|
+
# or
|
|
37
|
+
rake rubocop
|
|
38
|
+
rake spec
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Matrixed Rails versions use [Appraisal](https://github.com/thoughtbot/appraisal): `gemfiles/rails72.gemfile`, `rails8ruby34.gemfile`, and `rails8truffleruby.gemfile` pin Rails 7.2 / 8.1 (integration tests follow the `spec/dummy` app, which is tested from 7.2 upward). Run `bundle exec appraisal rspec` to execute RSpec in each gemfile context, or `bundle exec parallel_rspec spec` locally for faster multi-process runs on the current bundle.
|
|
42
|
+
|
|
43
|
+
[Trunk](https://docs.trunk.io) config lives in `.trunk/`; CI runs `trunk` via `.github/workflows/trunk.yml`. Releases: `usr/bin/release.rb` (RuboCop, Appraisal RSpec across gemfiles, `gem build` / `gem push`, git tag, `gh release`).
|
|
44
|
+
|
|
45
|
+
No local ActiveAdmin checkout is required; the dummy app depends on the published `activeadmin` gem like a normal host app.
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT — see [LICENSE.md](LICENSE.md).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/active_admin/graphql/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "activeadmin-graphql"
|
|
7
|
+
spec.version = ActiveAdmin::GraphQL::VERSION
|
|
8
|
+
spec.authors = ["Andrei Makarov"]
|
|
9
|
+
spec.email = ["contact@kiskolabs.com"]
|
|
10
|
+
spec.summary = "GraphQL API extension for ActiveAdmin (graphql-ruby)."
|
|
11
|
+
spec.description = "Exposes ActiveAdmin resources and pages as a graphql-ruby schema with an HTTP endpoint per namespace."
|
|
12
|
+
spec.license = "MIT"
|
|
13
|
+
spec.platform = Gem::Platform::RUBY
|
|
14
|
+
spec.required_ruby_version = ">= 3.2"
|
|
15
|
+
|
|
16
|
+
repository_url = "https://github.com/amkisko/activeadmin-graphql"
|
|
17
|
+
|
|
18
|
+
spec.homepage = repository_url
|
|
19
|
+
spec.metadata = {
|
|
20
|
+
"homepage_uri" => repository_url,
|
|
21
|
+
"source_code_uri" => "#{repository_url}/tree/main",
|
|
22
|
+
"changelog_uri" => "#{repository_url}/blob/main/CHANGELOG.md",
|
|
23
|
+
"documentation_uri" => "#{repository_url}/blob/main/docs/graphql-api.md",
|
|
24
|
+
"bug_tracker_uri" => "#{repository_url}/issues",
|
|
25
|
+
"rubygems_mfa_required" => "true"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
29
|
+
%w[
|
|
30
|
+
CHANGELOG.md
|
|
31
|
+
CODE_OF_CONDUCT.md
|
|
32
|
+
CONTRIBUTING.md
|
|
33
|
+
LICENSE.md
|
|
34
|
+
README.md
|
|
35
|
+
activeadmin-graphql.gemspec
|
|
36
|
+
].select { |f| File.file?(f) } +
|
|
37
|
+
Dir["docs/**/*.md"] +
|
|
38
|
+
Dir["app/**/*.rb"] +
|
|
39
|
+
Dir["lib/**/*.rb"]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
spec.require_paths = ["lib"]
|
|
43
|
+
|
|
44
|
+
spec.add_runtime_dependency "activeadmin", ">= 3.2"
|
|
45
|
+
spec.add_runtime_dependency "graphql", ">= 2.3"
|
|
46
|
+
|
|
47
|
+
spec.add_development_dependency "appraisal", "~> 2"
|
|
48
|
+
spec.add_development_dependency "bigdecimal"
|
|
49
|
+
spec.add_development_dependency "bundler", ">= 2"
|
|
50
|
+
spec.add_development_dependency "devise", ">= 4.9"
|
|
51
|
+
spec.add_development_dependency "parallel_tests", "~> 4.7"
|
|
52
|
+
spec.add_development_dependency "rails", ">= 6.1"
|
|
53
|
+
spec.add_development_dependency "rspec", "~> 3"
|
|
54
|
+
spec.add_development_dependency "rspec-rails", ">= 6"
|
|
55
|
+
spec.add_development_dependency "rubocop-rails", "~> 2.34"
|
|
56
|
+
spec.add_development_dependency "rubocop-rspec", "~> 3.8"
|
|
57
|
+
spec.add_development_dependency "rubocop-thread_safety", "~> 0.7"
|
|
58
|
+
spec.add_development_dependency "simplecov", "~> 0.22"
|
|
59
|
+
spec.add_development_dependency "sprockets-rails", ">= 3.4"
|
|
60
|
+
spec.add_development_dependency "sqlite3", ">= 1"
|
|
61
|
+
spec.add_development_dependency "standard", "~> 1.52"
|
|
62
|
+
spec.add_development_dependency "standard-custom", "~> 1.0"
|
|
63
|
+
spec.add_development_dependency "standard-performance", "~> 1.8"
|
|
64
|
+
spec.add_development_dependency "standard-rails", "~> 1.5"
|
|
65
|
+
spec.add_development_dependency "standard-rspec", "~> 0.3"
|
|
66
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAdmin
|
|
4
|
+
# HTTP endpoint for the namespace GraphQL schema (graphql-ruby).
|
|
5
|
+
#
|
|
6
|
+
# Authentication runs before any GraphQL work, including introspection.
|
|
7
|
+
# Supports single operations (+application/json+ body or form params) and
|
|
8
|
+
# multiplexed batches (+application/json+ array documented by graphql-ruby).
|
|
9
|
+
class GraphqlController < ApplicationController
|
|
10
|
+
protect_from_forgery with: :exception
|
|
11
|
+
|
|
12
|
+
before_action :ensure_graphql_enabled!
|
|
13
|
+
before_action :authenticate_graphql!
|
|
14
|
+
|
|
15
|
+
def execute
|
|
16
|
+
schema = ActiveAdmin::GraphQL.schema_for(active_admin_namespace)
|
|
17
|
+
|
|
18
|
+
if multiplex_request?
|
|
19
|
+
operations = multiplex_operations
|
|
20
|
+
max_n = active_admin_namespace.graphql_multiplex_max || 20
|
|
21
|
+
if operations.size > max_n
|
|
22
|
+
return render json: {errors: [{message: "Multiplex exceeds maximum of #{max_n}"}]},
|
|
23
|
+
status: :content_too_large
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
results = schema.multiplex(
|
|
27
|
+
operations.map do |op|
|
|
28
|
+
{
|
|
29
|
+
query: op[:query],
|
|
30
|
+
variables: ensure_variables(op[:variables]),
|
|
31
|
+
operation_name: op[:operation_name],
|
|
32
|
+
context: graphql_context
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
)
|
|
36
|
+
render json: results.map(&:to_h), status: :ok
|
|
37
|
+
else
|
|
38
|
+
result = schema.execute(
|
|
39
|
+
query: query_string,
|
|
40
|
+
variables: ensure_variables(variables_hash),
|
|
41
|
+
operation_name: operation_name,
|
|
42
|
+
context: graphql_context
|
|
43
|
+
)
|
|
44
|
+
render json: result.to_h, status: :ok
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def active_admin_namespace
|
|
49
|
+
key = request.path_parameters[:active_admin_namespace] || params[:active_admin_namespace]
|
|
50
|
+
raise ActionController::RoutingError, "Missing active_admin_namespace route default" unless key
|
|
51
|
+
|
|
52
|
+
ActiveAdmin.application.namespaces[key.to_sym].tap do |ns|
|
|
53
|
+
raise ActionController::RoutingError, "Unknown ActiveAdmin namespace: #{key}" unless ns
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def ensure_graphql_enabled!
|
|
60
|
+
return if active_admin_namespace.graphql
|
|
61
|
+
head :not_found and return
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def authenticate_graphql!
|
|
65
|
+
meth = active_admin_namespace.authentication_method
|
|
66
|
+
send(meth) if meth
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def current_active_admin_user
|
|
70
|
+
meth = active_admin_namespace.current_user_method
|
|
71
|
+
send(meth) if meth
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def graphql_context
|
|
75
|
+
ns = active_admin_namespace
|
|
76
|
+
{
|
|
77
|
+
auth: ActiveAdmin::GraphQL::AuthContext.new(
|
|
78
|
+
user: current_active_admin_user,
|
|
79
|
+
namespace: ns
|
|
80
|
+
),
|
|
81
|
+
namespace: ns,
|
|
82
|
+
request: request,
|
|
83
|
+
current_user: current_active_admin_user,
|
|
84
|
+
visibility_profile: graphql_visibility_profile_for(ns)
|
|
85
|
+
}.compact
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def graphql_visibility_profile_for(ns)
|
|
89
|
+
prof = ns.graphql_visibility_profile
|
|
90
|
+
return nil if prof.blank?
|
|
91
|
+
|
|
92
|
+
prof.to_sym
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def multiplex_request?
|
|
96
|
+
request.post? && raw_operation_array
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def raw_operation_array
|
|
100
|
+
parsed = request_body_json
|
|
101
|
+
return parsed if parsed.is_a?(Array)
|
|
102
|
+
|
|
103
|
+
params[:_json] if params[:_json].is_a?(Array)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def multiplex_operations
|
|
107
|
+
raw_operation_array.map { |payload| normalize_operation(payload) }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def normalize_operation(payload)
|
|
111
|
+
h = payload.stringify_keys
|
|
112
|
+
{
|
|
113
|
+
query: h["query"],
|
|
114
|
+
variables: h["variables"],
|
|
115
|
+
operation_name: h["operationName"] || h["operation_name"]
|
|
116
|
+
}
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def query_string
|
|
120
|
+
params[:query] || request_body_hash&.dig("query")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def operation_name
|
|
124
|
+
params[:operationName] || params[:operation_name] || request_body_hash&.dig("operationName")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def variables_hash
|
|
128
|
+
params[:variables] || request_body_hash&.dig("variables")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def request_body_hash
|
|
132
|
+
json = request_body_json
|
|
133
|
+
json if json.is_a?(Hash)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def request_body_json
|
|
137
|
+
return @request_body_json if defined?(@request_body_json)
|
|
138
|
+
|
|
139
|
+
@request_body_json =
|
|
140
|
+
if request.body.nil?
|
|
141
|
+
nil
|
|
142
|
+
else
|
|
143
|
+
body = request.body.read
|
|
144
|
+
request.body.rewind
|
|
145
|
+
body.present? ? JSON.parse(body) : nil
|
|
146
|
+
end
|
|
147
|
+
rescue JSON::ParserError
|
|
148
|
+
@request_body_json = nil
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def ensure_variables(raw)
|
|
152
|
+
case raw
|
|
153
|
+
when String
|
|
154
|
+
raw.present? ? JSON.parse(raw) : {}
|
|
155
|
+
when Hash
|
|
156
|
+
raw
|
|
157
|
+
when ActionController::Parameters
|
|
158
|
+
raw.to_unsafe_h
|
|
159
|
+
when nil
|
|
160
|
+
{}
|
|
161
|
+
else
|
|
162
|
+
{}
|
|
163
|
+
end
|
|
164
|
+
rescue JSON::ParserError
|
|
165
|
+
{}
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|