add graphql endpoint
This commit is contained in:
8
Gemfile
8
Gemfile
@@ -12,16 +12,17 @@ gem "rails", "~> 6.1.4"
|
|||||||
gem "sass-rails", ">= 6"
|
gem "sass-rails", ">= 6"
|
||||||
gem "turbolinks", "~> 5"
|
gem "turbolinks", "~> 5"
|
||||||
gem "webpacker", "~> 5.0"
|
gem "webpacker", "~> 5.0"
|
||||||
|
|
||||||
gem "bootsnap", ">= 1.4.4", require: false
|
gem "bootsnap", ">= 1.4.4", require: false
|
||||||
|
|
||||||
gem "administrate"
|
|
||||||
|
|
||||||
gem "devise"
|
gem "devise"
|
||||||
gem "devise-bootstrap-views", "~> 1.0"
|
gem "devise-bootstrap-views", "~> 1.0"
|
||||||
gem "devise-i18n"
|
gem "devise-i18n"
|
||||||
|
|
||||||
|
gem "administrate"
|
||||||
|
gem "graphql"
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
|
gem "graphql_playground-rails"
|
||||||
gem "pry-byebug", platforms: [:mri, :mingw, :x64_mingw]
|
gem "pry-byebug", platforms: [:mri, :mingw, :x64_mingw]
|
||||||
gem "capybara"
|
gem "capybara"
|
||||||
gem "rspec-rails"
|
gem "rspec-rails"
|
||||||
@@ -32,6 +33,7 @@ group :development, :test do
|
|||||||
end
|
end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
|
gem "graphql_playground-rails"
|
||||||
gem "web-console", ">= 4.1.0"
|
gem "web-console", ">= 4.1.0"
|
||||||
|
|
||||||
gem "listen", "~> 3.3"
|
gem "listen", "~> 3.3"
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ GEM
|
|||||||
ffi (1.15.3)
|
ffi (1.15.3)
|
||||||
globalid (0.5.2)
|
globalid (0.5.2)
|
||||||
activesupport (>= 5.0)
|
activesupport (>= 5.0)
|
||||||
|
graphql (1.12.14)
|
||||||
|
graphql_playground-rails (2.1.0)
|
||||||
|
rails (>= 5.1.0)
|
||||||
i18n (1.8.10)
|
i18n (1.8.10)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
jbuilder (2.11.2)
|
jbuilder (2.11.2)
|
||||||
@@ -299,6 +302,8 @@ DEPENDENCIES
|
|||||||
devise
|
devise
|
||||||
devise-bootstrap-views (~> 1.0)
|
devise-bootstrap-views (~> 1.0)
|
||||||
devise-i18n
|
devise-i18n
|
||||||
|
graphql
|
||||||
|
graphql_playground-rails
|
||||||
jbuilder (~> 2.7)
|
jbuilder (~> 2.7)
|
||||||
listen (~> 3.3)
|
listen (~> 3.3)
|
||||||
pg (~> 1.1)
|
pg (~> 1.1)
|
||||||
|
|||||||
51
app/controllers/graphql_controller.rb
Normal file
51
app/controllers/graphql_controller.rb
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class GraphqlController < ApplicationController
|
||||||
|
# If accessing from outside this domain, nullify the session
|
||||||
|
# This allows for outside API access while preventing CSRF attacks,
|
||||||
|
# but you'll have to authenticate your user separately
|
||||||
|
# protect_from_forgery with: :null_session
|
||||||
|
|
||||||
|
def execute
|
||||||
|
variables = prepare_variables(params[:variables])
|
||||||
|
query = params[:query]
|
||||||
|
operation_name = params[:operationName]
|
||||||
|
context = {
|
||||||
|
# Query context goes here, for example:
|
||||||
|
current_user: current_admin_user,
|
||||||
|
}
|
||||||
|
result = XStakeSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
|
||||||
|
render(json: result)
|
||||||
|
rescue StandardError => e
|
||||||
|
raise e unless Rails.env.development?
|
||||||
|
handle_error_in_development(e)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Handle variables in form data, JSON body, or a blank value
|
||||||
|
def prepare_variables(variables_param)
|
||||||
|
case variables_param
|
||||||
|
when String
|
||||||
|
if variables_param.present?
|
||||||
|
JSON.parse(variables_param) || {}
|
||||||
|
else
|
||||||
|
{}
|
||||||
|
end
|
||||||
|
when Hash
|
||||||
|
variables_param
|
||||||
|
when ActionController::Parameters
|
||||||
|
variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
|
||||||
|
when nil
|
||||||
|
{}
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Unexpected parameter: #{variables_param}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_error_in_development(e)
|
||||||
|
logger.error(e.message)
|
||||||
|
logger.error(e.backtrace.join("\n"))
|
||||||
|
|
||||||
|
render(json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: :internal_server_error)
|
||||||
|
end
|
||||||
|
end
|
||||||
0
app/graphql/mutations/.keep
Normal file
0
app/graphql/mutations/.keep
Normal file
9
app/graphql/mutations/base_mutation.rb
Normal file
9
app/graphql/mutations/base_mutation.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Mutations
|
||||||
|
class BaseMutation < GraphQL::Schema::RelayClassicMutation
|
||||||
|
argument_class Types::BaseArgument
|
||||||
|
field_class Types::BaseField
|
||||||
|
input_object_class Types::BaseInputObject
|
||||||
|
object_class Types::BaseObject
|
||||||
|
end
|
||||||
|
end
|
||||||
0
app/graphql/types/.keep
Normal file
0
app/graphql/types/.keep
Normal file
5
app/graphql/types/base_argument.rb
Normal file
5
app/graphql/types/base_argument.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseArgument < GraphQL::Schema::Argument
|
||||||
|
end
|
||||||
|
end
|
||||||
7
app/graphql/types/base_connection.rb
Normal file
7
app/graphql/types/base_connection.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseConnection < Types::BaseObject
|
||||||
|
# add `nodes` and `pageInfo` fields, as well as `edge_type(...)` and `node_nullable(...)` overrides
|
||||||
|
include GraphQL::Types::Relay::ConnectionBehaviors
|
||||||
|
end
|
||||||
|
end
|
||||||
7
app/graphql/types/base_edge.rb
Normal file
7
app/graphql/types/base_edge.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseEdge < Types::BaseObject
|
||||||
|
# add `node` and `cursor` fields, as well as `node_type(...)` override
|
||||||
|
include GraphQL::Types::Relay::EdgeBehaviors
|
||||||
|
end
|
||||||
|
end
|
||||||
5
app/graphql/types/base_enum.rb
Normal file
5
app/graphql/types/base_enum.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseEnum < GraphQL::Schema::Enum
|
||||||
|
end
|
||||||
|
end
|
||||||
6
app/graphql/types/base_field.rb
Normal file
6
app/graphql/types/base_field.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseField < GraphQL::Schema::Field
|
||||||
|
argument_class Types::BaseArgument
|
||||||
|
end
|
||||||
|
end
|
||||||
6
app/graphql/types/base_input_object.rb
Normal file
6
app/graphql/types/base_input_object.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseInputObject < GraphQL::Schema::InputObject
|
||||||
|
argument_class Types::BaseArgument
|
||||||
|
end
|
||||||
|
end
|
||||||
10
app/graphql/types/base_interface.rb
Normal file
10
app/graphql/types/base_interface.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
module BaseInterface
|
||||||
|
include GraphQL::Schema::Interface
|
||||||
|
edge_type_class(Types::BaseEdge)
|
||||||
|
connection_type_class(Types::BaseConnection)
|
||||||
|
|
||||||
|
field_class Types::BaseField
|
||||||
|
end
|
||||||
|
end
|
||||||
8
app/graphql/types/base_object.rb
Normal file
8
app/graphql/types/base_object.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseObject < GraphQL::Schema::Object
|
||||||
|
edge_type_class(Types::BaseEdge)
|
||||||
|
connection_type_class(Types::BaseConnection)
|
||||||
|
field_class Types::BaseField
|
||||||
|
end
|
||||||
|
end
|
||||||
5
app/graphql/types/base_scalar.rb
Normal file
5
app/graphql/types/base_scalar.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseScalar < GraphQL::Schema::Scalar
|
||||||
|
end
|
||||||
|
end
|
||||||
7
app/graphql/types/base_union.rb
Normal file
7
app/graphql/types/base_union.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class BaseUnion < GraphQL::Schema::Union
|
||||||
|
edge_type_class(Types::BaseEdge)
|
||||||
|
connection_type_class(Types::BaseConnection)
|
||||||
|
end
|
||||||
|
end
|
||||||
11
app/graphql/types/mutation_type.rb
Normal file
11
app/graphql/types/mutation_type.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class MutationType < Types::BaseObject
|
||||||
|
# TODO: remove me
|
||||||
|
field :test_field, String, null: false,
|
||||||
|
description: "An example field added by the generator"
|
||||||
|
def test_field
|
||||||
|
"Hello World"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
8
app/graphql/types/node_type.rb
Normal file
8
app/graphql/types/node_type.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
module NodeType
|
||||||
|
include Types::BaseInterface
|
||||||
|
# Add the `id` field
|
||||||
|
include GraphQL::Types::Relay::NodeBehaviors
|
||||||
|
end
|
||||||
|
end
|
||||||
18
app/graphql/types/query_type.rb
Normal file
18
app/graphql/types/query_type.rb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class QueryType < Types::BaseObject
|
||||||
|
# Add `node(id: ID!) and `nodes(ids: [ID!]!)`
|
||||||
|
include GraphQL::Types::Relay::HasNodeField
|
||||||
|
include GraphQL::Types::Relay::HasNodesField
|
||||||
|
|
||||||
|
# Add root-level fields here.
|
||||||
|
# They will be entry points for queries on your schema.
|
||||||
|
|
||||||
|
# TODO: remove me
|
||||||
|
field :test_field, String, null: false,
|
||||||
|
description: "An example field added by the generator"
|
||||||
|
def test_field
|
||||||
|
context[:current_user].email
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
18
app/graphql/x_stake_schema.rb
Normal file
18
app/graphql/x_stake_schema.rb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class XStakeSchema < GraphQL::Schema
|
||||||
|
mutation(Types::MutationType)
|
||||||
|
query(Types::QueryType)
|
||||||
|
|
||||||
|
def self.resolve_type(abstract_type, obj, ctx)
|
||||||
|
raise(GraphQL::RequiredImplementationMissingError)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.id_from_object(object, type_definition, query_ctx)
|
||||||
|
GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.object_from_id(id, query_ctx)
|
||||||
|
type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
|
||||||
|
type_name.constantize.find(item_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
|
mount GraphqlPlayground::Rails::Engine, at: "/playground", graphql_path: "/graphql" if Rails.env.development?
|
||||||
|
|
||||||
|
post "/graphql", to: "graphql#execute"
|
||||||
|
|
||||||
|
devise_for :admin_users
|
||||||
|
|
||||||
namespace :admin do
|
namespace :admin do
|
||||||
resources :admin_users
|
resources :admin_users
|
||||||
|
|
||||||
root to: "admin_users#index"
|
root to: "admin_users#index"
|
||||||
end
|
end
|
||||||
|
|
||||||
devise_for :admin_users
|
|
||||||
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user