graphql 1.4.5 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/enum_generator.rb +33 -0
- data/lib/generators/graphql/function_generator.rb +15 -0
- data/lib/generators/graphql/install_generator.rb +118 -0
- data/lib/generators/graphql/interface_generator.rb +27 -0
- data/lib/generators/graphql/loader_generator.rb +17 -0
- data/lib/generators/graphql/mutation_generator.rb +19 -0
- data/lib/generators/graphql/object_generator.rb +34 -0
- data/lib/generators/graphql/templates/enum.erb +4 -0
- data/lib/generators/graphql/templates/function.erb +17 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +32 -0
- data/lib/generators/graphql/templates/interface.erb +4 -0
- data/lib/generators/graphql/templates/loader.erb +15 -0
- data/lib/generators/graphql/templates/mutation.erb +12 -0
- data/lib/generators/graphql/templates/object.erb +5 -0
- data/lib/generators/graphql/templates/query_type.erb +15 -0
- data/lib/generators/graphql/templates/schema.erb +34 -0
- data/lib/generators/graphql/templates/union.erb +4 -0
- data/lib/generators/graphql/type_generator.rb +78 -0
- data/lib/generators/graphql/union_generator.rb +33 -0
- data/lib/graphql.rb +10 -0
- data/lib/graphql/analysis/analyze_query.rb +1 -1
- data/lib/graphql/analysis/query_complexity.rb +6 -50
- data/lib/graphql/analysis/query_depth.rb +1 -1
- data/lib/graphql/argument.rb +21 -0
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +3 -3
- data/lib/graphql/define.rb +1 -0
- data/lib/graphql/define/assign_argument.rb +3 -19
- data/lib/graphql/define/assign_mutation_function.rb +34 -0
- data/lib/graphql/define/assign_object_field.rb +26 -14
- data/lib/graphql/define/defined_object_proxy.rb +21 -0
- data/lib/graphql/define/instance_definable.rb +61 -11
- data/lib/graphql/directive.rb +6 -1
- data/lib/graphql/execution/directive_checks.rb +1 -0
- data/lib/graphql/execution/execute.rb +14 -9
- data/lib/graphql/execution/field_result.rb +1 -0
- data/lib/graphql/execution/lazy.rb +8 -17
- data/lib/graphql/execution/lazy/lazy_method_map.rb +2 -0
- data/lib/graphql/execution/lazy/resolve.rb +1 -0
- data/lib/graphql/execution/selection_result.rb +1 -0
- data/lib/graphql/execution/typecast.rb +39 -26
- data/lib/graphql/field.rb +15 -3
- data/lib/graphql/field/resolve.rb +3 -3
- data/lib/graphql/function.rb +134 -0
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +1 -1
- data/lib/graphql/internal_representation.rb +1 -1
- data/lib/graphql/internal_representation/node.rb +35 -107
- data/lib/graphql/internal_representation/rewrite.rb +189 -183
- data/lib/graphql/internal_representation/visit.rb +38 -0
- data/lib/graphql/introspection/input_value_type.rb +10 -1
- data/lib/graphql/introspection/schema_type.rb +1 -1
- data/lib/graphql/language/lexer.rb +6 -3
- data/lib/graphql/language/lexer.rl +6 -3
- data/lib/graphql/object_type.rb +53 -13
- data/lib/graphql/query.rb +30 -14
- data/lib/graphql/query/arguments.rb +2 -0
- data/lib/graphql/query/context.rb +2 -2
- data/lib/graphql/query/literal_input.rb +9 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +2 -2
- data/lib/graphql/query/serial_execution/selection_resolution.rb +1 -1
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/relay/array_connection.rb +1 -1
- data/lib/graphql/relay/base_connection.rb +34 -15
- data/lib/graphql/relay/connection_resolve.rb +7 -2
- data/lib/graphql/relay/mutation.rb +45 -4
- data/lib/graphql/relay/node.rb +18 -6
- data/lib/graphql/relay/range_add.rb +45 -0
- data/lib/graphql/relay/relation_connection.rb +17 -2
- data/lib/graphql/runtime_type_error.rb +1 -0
- data/lib/graphql/schema.rb +40 -5
- data/lib/graphql/schema/base_64_encoder.rb +1 -0
- data/lib/graphql/schema/build_from_definition.rb +56 -21
- data/lib/graphql/schema/default_parse_error.rb +10 -0
- data/lib/graphql/schema/loader.rb +8 -1
- data/lib/graphql/schema/null_mask.rb +1 -0
- data/lib/graphql/schema/validation.rb +35 -0
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/arguments_validator.rb +7 -4
- data/lib/graphql/static_validation/definition_dependencies.rb +183 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +28 -96
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +23 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -5
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +6 -31
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +11 -41
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +2 -2
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -7
- data/lib/graphql/static_validation/validation_context.rb +22 -1
- data/lib/graphql/static_validation/validator.rb +4 -1
- data/lib/graphql/string_type.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +12 -3
- data/spec/generators/graphql/enum_generator_spec.rb +29 -0
- data/spec/generators/graphql/function_generator_spec.rb +33 -0
- data/spec/generators/graphql/install_generator_spec.rb +185 -0
- data/spec/generators/graphql/interface_generator_spec.rb +32 -0
- data/spec/generators/graphql/loader_generator_spec.rb +31 -0
- data/spec/generators/graphql/mutation_generator_spec.rb +28 -0
- data/spec/generators/graphql/object_generator_spec.rb +42 -0
- data/spec/generators/graphql/union_generator_spec.rb +50 -0
- data/spec/graphql/analysis/query_complexity_spec.rb +2 -1
- data/spec/graphql/define/instance_definable_spec.rb +38 -0
- data/spec/graphql/directive/skip_directive_spec.rb +1 -0
- data/spec/graphql/directive_spec.rb +18 -0
- data/spec/graphql/execution/typecast_spec.rb +41 -46
- data/spec/graphql/field_spec.rb +1 -1
- data/spec/graphql/function_spec.rb +128 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +166 -129
- data/spec/graphql/introspection/type_type_spec.rb +1 -1
- data/spec/graphql/language/lexer_spec.rb +6 -0
- data/spec/graphql/object_type_spec.rb +73 -2
- data/spec/graphql/query/arguments_spec.rb +28 -0
- data/spec/graphql/query/variables_spec.rb +7 -1
- data/spec/graphql/query_spec.rb +30 -0
- data/spec/graphql/relay/base_connection_spec.rb +26 -8
- data/spec/graphql/relay/connection_resolve_spec.rb +45 -0
- data/spec/graphql/relay/connection_type_spec.rb +21 -0
- data/spec/graphql/relay/node_spec.rb +30 -2
- data/spec/graphql/relay/range_add_spec.rb +113 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +114 -0
- data/spec/graphql/schema/loader_spec.rb +1 -0
- data/spec/graphql/schema/printer_spec.rb +2 -2
- data/spec/graphql/schema/validation_spec.rb +80 -11
- data/spec/graphql/schema/warden_spec.rb +10 -10
- data/spec/graphql/schema_spec.rb +18 -1
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +16 -0
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +50 -3
- data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +27 -0
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +57 -0
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +14 -0
- data/spec/graphql/string_type_spec.rb +7 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/support/base_generator_test.rb +7 -0
- data/spec/support/dummy/schema.rb +32 -30
- data/spec/support/star_wars/schema.rb +81 -23
- metadata +98 -20
- data/lib/graphql/internal_representation/selection.rb +0 -85
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8a07faba9f807e0d1a1cb2d658dbb03aebd5aff
|
4
|
+
data.tar.gz: 7cc789d4ff25519e433770bab5fbdff0421338c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4699ee8d911f2a26824b08f938bec2d3b564f28864491d355d242e91dd79b17de8b301d91f8016409cf76da93e811364620bb24637a81a616093df5a16a2035
|
7
|
+
data.tar.gz: f805fd9332370ceb6876dc9e68178a5f1753edb6993e14881eba5b36bb7935502a7419c7a0d03fd0b405533be943f4cc4db50f430b7f61cafd331a3ab97a7858
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'generators/graphql/type_generator'
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
# Generate an interface type by name,
|
7
|
+
# with the specified fields.
|
8
|
+
#
|
9
|
+
# ```
|
10
|
+
# rails g graphql:interface NamedEntityType name:String!
|
11
|
+
# ```
|
12
|
+
class EnumGenerator < TypeGeneratorBase
|
13
|
+
desc "Create a GraphQL::EnumType with the given name and values"
|
14
|
+
source_root File.expand_path('../templates', __FILE__)
|
15
|
+
|
16
|
+
argument :values,
|
17
|
+
type: :array,
|
18
|
+
default: [],
|
19
|
+
banner: "value{:ruby_value} value{:ruby_value} ...",
|
20
|
+
desc: "Values for this enum (if present, ruby_value will be inserted verbatim)"
|
21
|
+
|
22
|
+
def create_type_file
|
23
|
+
template "enum.erb", "app/graphql/types/#{type_file_name}.rb"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def prepared_values
|
29
|
+
values.map { |v| v.split(":", 2) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "rails/generators/named_base"
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
class FunctionGenerator < Rails::Generators::NamedBase
|
7
|
+
desc "Create a GraphQL::Function by name"
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
|
10
|
+
def create_function_file
|
11
|
+
template "function.erb", "app/graphql/functions/#{file_name}.rb"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rails/generators/base'
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
# Add GraphQL to a Rails app with `rails g graphql:install`.
|
7
|
+
#
|
8
|
+
# Setup a folder structure for GraphQL:
|
9
|
+
#
|
10
|
+
# ```
|
11
|
+
# - app/
|
12
|
+
# - graphql/
|
13
|
+
# - resolvers/
|
14
|
+
# - types/
|
15
|
+
# - query_type.rb
|
16
|
+
# - loaders/
|
17
|
+
# - mutations/
|
18
|
+
# - {app_name}_schema.rb
|
19
|
+
# ```
|
20
|
+
#
|
21
|
+
# (Add `.gitkeep`s by default, support `--skip-keeps`)
|
22
|
+
#
|
23
|
+
# Add a controller for serving GraphQL queries:
|
24
|
+
#
|
25
|
+
# ```
|
26
|
+
# app/controllers/graphql_controller.rb
|
27
|
+
# ```
|
28
|
+
#
|
29
|
+
# Add a route for that controller:
|
30
|
+
#
|
31
|
+
# ```ruby
|
32
|
+
# # config/routes.rb
|
33
|
+
# post "/graphql", to: "graphql#execute"
|
34
|
+
# ```
|
35
|
+
#
|
36
|
+
# Accept a `--relay` option which adds
|
37
|
+
# The root `node(id: ID!)` field.
|
38
|
+
#
|
39
|
+
# Accept a `--batch` option which adds `GraphQL::Batch` setup.
|
40
|
+
#
|
41
|
+
# Use `--no-graphiql` to skip `graphiql-rails` installation.
|
42
|
+
class InstallGenerator < Rails::Generators::Base
|
43
|
+
desc "Install GraphQL folder structure and boilerplate code"
|
44
|
+
source_root File.expand_path('../templates', __FILE__)
|
45
|
+
|
46
|
+
class_option :schema,
|
47
|
+
type: :string,
|
48
|
+
default: nil,
|
49
|
+
desc: "Name for the schema constant (default: {app_name}Schema)"
|
50
|
+
|
51
|
+
class_option :skip_keeps,
|
52
|
+
type: :boolean,
|
53
|
+
default: false,
|
54
|
+
desc: "Skip .keep files for source control"
|
55
|
+
|
56
|
+
class_option :skip_graphiql,
|
57
|
+
type: :boolean,
|
58
|
+
default: false,
|
59
|
+
desc: "Skip graphiql-rails installation"
|
60
|
+
|
61
|
+
class_option :relay,
|
62
|
+
type: :boolean,
|
63
|
+
default: false,
|
64
|
+
desc: "Include GraphQL::Relay installation"
|
65
|
+
|
66
|
+
class_option :batch,
|
67
|
+
type: :boolean,
|
68
|
+
default: false,
|
69
|
+
desc: "Include GraphQL::Batch installation"
|
70
|
+
|
71
|
+
|
72
|
+
GRAPHIQL_ROUTE = <<-RUBY
|
73
|
+
if Rails.env.development?
|
74
|
+
mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
|
75
|
+
end
|
76
|
+
RUBY
|
77
|
+
|
78
|
+
def create_folder_structure
|
79
|
+
create_dir("app/graphql/mutations")
|
80
|
+
create_dir("app/graphql/types")
|
81
|
+
template("query_type.erb", "app/graphql/types/query_type.rb")
|
82
|
+
template("schema.erb", "app/graphql/#{schema_name.underscore}.rb")
|
83
|
+
template("graphql_controller.erb", "app/controllers/graphql_controller.rb")
|
84
|
+
route('post "/graphql", to: "graphql#execute"')
|
85
|
+
|
86
|
+
if !options[:skip_graphiql]
|
87
|
+
gem("graphiql-rails", group: :development)
|
88
|
+
route(GRAPHIQL_ROUTE)
|
89
|
+
end
|
90
|
+
|
91
|
+
if options[:batch]
|
92
|
+
gem("graphql-batch")
|
93
|
+
create_dir("app/graphql/loaders")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def create_dir(dir)
|
100
|
+
empty_directory(dir)
|
101
|
+
if !options[:skip_keeps]
|
102
|
+
create_file("#{dir}/.keep")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def schema_name
|
107
|
+
@schema_name ||= begin
|
108
|
+
if options[:schema]
|
109
|
+
options[:schema]
|
110
|
+
else
|
111
|
+
require File.expand_path("config/application", destination_root)
|
112
|
+
"#{Rails.application.class.parent_name}Schema"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'generators/graphql/type_generator'
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
# Generate an interface type by name,
|
7
|
+
# with the specified fields.
|
8
|
+
#
|
9
|
+
# ```
|
10
|
+
# rails g graphql:interface NamedEntityType name:String!
|
11
|
+
# ```
|
12
|
+
class InterfaceGenerator < TypeGeneratorBase
|
13
|
+
desc "Create a GraphQL::InterfaceType with the given name and fields"
|
14
|
+
source_root File.expand_path('../templates', __FILE__)
|
15
|
+
|
16
|
+
argument :fields,
|
17
|
+
type: :array,
|
18
|
+
default: [],
|
19
|
+
banner: "name:type name:type ...",
|
20
|
+
desc: "Fields for this interface (type may be expressed as Ruby or GraphQL)"
|
21
|
+
|
22
|
+
def create_type_file
|
23
|
+
template "interface.erb", "app/graphql/types/#{type_file_name}.rb"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "rails/generators/named_base"
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
# @example Generate a `GraphQL::Batch` loader by name.
|
7
|
+
# rails g graphql:loader RecordLoader
|
8
|
+
class LoaderGenerator < Rails::Generators::NamedBase
|
9
|
+
desc "Create a GraphQL::Batch::Loader by name"
|
10
|
+
source_root File.expand_path('../templates', __FILE__)
|
11
|
+
|
12
|
+
def create_loader_file
|
13
|
+
template "loader.erb", "app/graphql/loaders/#{file_name}.rb"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rails/generators/named_base'
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
# TODO: What other options should be supported?
|
7
|
+
#
|
8
|
+
# @example Generate a `Relay::Mutation` by name
|
9
|
+
# rails g graphql:mutation CreatePostMutation
|
10
|
+
class MutationGenerator < Rails::Generators::NamedBase
|
11
|
+
desc "Create a Relay mutation by name"
|
12
|
+
source_root File.expand_path('../templates', __FILE__)
|
13
|
+
|
14
|
+
def create_mutation_file
|
15
|
+
template "mutation.erb", "app/graphql/mutations/#{file_name}.rb"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'generators/graphql/type_generator'
|
3
|
+
|
4
|
+
module Graphql
|
5
|
+
module Generators
|
6
|
+
# Generate an object type by name,
|
7
|
+
# with the specified fields.
|
8
|
+
#
|
9
|
+
# ```
|
10
|
+
# rails g graphql:object PostType name:String!
|
11
|
+
# ```
|
12
|
+
#
|
13
|
+
# Add the Node interface with `--node`.
|
14
|
+
class ObjectGenerator < TypeGeneratorBase
|
15
|
+
desc "Create a GraphQL::ObjectType with the given name and fields"
|
16
|
+
source_root File.expand_path('../templates', __FILE__)
|
17
|
+
|
18
|
+
argument :fields,
|
19
|
+
type: :array,
|
20
|
+
default: [],
|
21
|
+
banner: "name:type name:type ...",
|
22
|
+
desc: "Fields for this object (type may be expressed as Ruby or GraphQL)"
|
23
|
+
|
24
|
+
class_option :node,
|
25
|
+
type: :boolean,
|
26
|
+
default: false,
|
27
|
+
desc: "Include the Relay Node interface"
|
28
|
+
|
29
|
+
def create_type_file
|
30
|
+
template "object.erb", "app/graphql/types/#{type_file_name}.rb"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Functions::<%= name %> < GraphQL::Function
|
2
|
+
# Define `initialize` to store field-level options, eg
|
3
|
+
#
|
4
|
+
# field :myField, function: Functions::<%= name %>.new(type: MyType)
|
5
|
+
#
|
6
|
+
# attr_reader :type
|
7
|
+
# def initialize(type:)
|
8
|
+
# @type = type
|
9
|
+
# end
|
10
|
+
|
11
|
+
# add arguments by type:
|
12
|
+
# argument :id, !GraphQL::ID_TYPE
|
13
|
+
|
14
|
+
# Resolve function:
|
15
|
+
def call(obj, args, ctx)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class GraphqlController < ApplicationController
|
2
|
+
def execute
|
3
|
+
variables = ensure_hash(params[:variables])
|
4
|
+
query = params[:query]
|
5
|
+
context = {
|
6
|
+
# Query context goes here, for example:
|
7
|
+
# current_user: current_user,
|
8
|
+
}
|
9
|
+
result = <%= schema_name %>.execute(query, variables: variables, context: context)
|
10
|
+
render json: result
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# Handle form data, JSON body, or a blank value
|
16
|
+
def ensure_hash(ambiguous_param)
|
17
|
+
case ambiguous_param
|
18
|
+
when String
|
19
|
+
if ambiguous_param.present?
|
20
|
+
ensure_hash(JSON.parse(ambiguous_param))
|
21
|
+
else
|
22
|
+
{}
|
23
|
+
end
|
24
|
+
when Hash, ActionController::Parameters
|
25
|
+
ambiguous_param
|
26
|
+
when nil
|
27
|
+
{}
|
28
|
+
else
|
29
|
+
raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Loaders::<%= name %> < GraphQL::Batch::Loader
|
2
|
+
# Define `initialize` to store grouping arguments, eg
|
3
|
+
#
|
4
|
+
# Loaders::<%= name %>.for(group).load(value)
|
5
|
+
#
|
6
|
+
# def initialize()
|
7
|
+
# end
|
8
|
+
|
9
|
+
# `keys` contains each key from `.load(key)`.
|
10
|
+
# Find the corresponding values, then
|
11
|
+
# call `fulfill(key, value)` or `fulfill(key, nil)`
|
12
|
+
# for each key.
|
13
|
+
def perform(keys)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Mutations::<%= name %> = GraphQL::Relay::Mutation.define do
|
2
|
+
name "<%= name %>"
|
3
|
+
# TODO: define return fields
|
4
|
+
# return_field :post, Types::PostType
|
5
|
+
|
6
|
+
# TODO: define arguments
|
7
|
+
# input_field :name, !types.String
|
8
|
+
|
9
|
+
resolve ->(obj, args, ctx) {
|
10
|
+
# TODO: define resolve function
|
11
|
+
}
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Types::QueryType = GraphQL::ObjectType.define do
|
2
|
+
name "Query"
|
3
|
+
# Add root-level fields here.
|
4
|
+
# They will be entry points for queries on your schema.
|
5
|
+
|
6
|
+
# TODO: remove me
|
7
|
+
field :testField, types.String do
|
8
|
+
description "An example field added by the generator"
|
9
|
+
resolve ->(obj, args, ctx) {
|
10
|
+
"Hello World!"
|
11
|
+
}
|
12
|
+
end
|
13
|
+
<% if options[:relay] %>
|
14
|
+
field :node, GraphQL::Relay::Node.field
|
15
|
+
<% end %>end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<%= schema_name %> = GraphQL::Schema.define do
|
2
|
+
query(Types::QueryType)
|
3
|
+
<% if options[:relay] %>
|
4
|
+
# Relay Object Identification:
|
5
|
+
|
6
|
+
# Return a string UUID for `object`
|
7
|
+
id_from_object ->(object, type_definition, query_ctx) {
|
8
|
+
# Here's a simple implementation which:
|
9
|
+
# - joins the type name & object.id
|
10
|
+
# - encodes it with base64:
|
11
|
+
# GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
|
12
|
+
}
|
13
|
+
|
14
|
+
# Given a string UUID, find the object
|
15
|
+
object_from_id ->(id, query_ctx) {
|
16
|
+
# For example, to decode the UUIDs generated above:
|
17
|
+
# type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
|
18
|
+
#
|
19
|
+
# Then, based on `type_name` and `id`
|
20
|
+
# find an object in your application
|
21
|
+
# ...
|
22
|
+
}
|
23
|
+
|
24
|
+
# Object Resolution
|
25
|
+
resolve_type -> (obj, ctx) {
|
26
|
+
# TODO: Implement this function
|
27
|
+
# to return the correct type for `obj`
|
28
|
+
raise(NotImplementedError)
|
29
|
+
}
|
30
|
+
<% end %><% if options[:batch] %>
|
31
|
+
# GraphQL::Batch setup:
|
32
|
+
lazy_resolve(Promise, :sync)
|
33
|
+
instrument(:query, GraphQL::Batch::Setup)
|
34
|
+
<% end %>end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rails/generators/base'
|
3
|
+
require 'graphql'
|
4
|
+
|
5
|
+
module Graphql
|
6
|
+
module Generators
|
7
|
+
class TypeGeneratorBase < Rails::Generators::Base
|
8
|
+
argument :type_name,
|
9
|
+
type: :string,
|
10
|
+
required: true,
|
11
|
+
banner: "TypeName",
|
12
|
+
desc: "Name of this object type (expressed as Ruby or GraphQL)"
|
13
|
+
|
14
|
+
# Take a type expression in any combination of GraphQL or Ruby styles
|
15
|
+
# and return it in a specified output style
|
16
|
+
# TODO: nullability / list with `mode: :graphql` doesn't work
|
17
|
+
# @param type_expresson [String]
|
18
|
+
# @param mode [Symbol]
|
19
|
+
# @return [String]
|
20
|
+
def self.normalize_type_expression(type_expression, mode:)
|
21
|
+
if type_expression.start_with?("!")
|
22
|
+
"!#{normalize_type_expression(type_expression[1..-1], mode: mode)}"
|
23
|
+
elsif type_expression.end_with?("!")
|
24
|
+
"!#{normalize_type_expression(type_expression[0..-2], mode: mode)}"
|
25
|
+
elsif type_expression.start_with?("[") && type_expression.end_with?("]")
|
26
|
+
"types[#{normalize_type_expression(type_expression[1..-2], mode: mode)}]"
|
27
|
+
elsif type_expression.start_with?("types[") && type_expression.end_with?("]")
|
28
|
+
"types[#{normalize_type_expression(type_expression[6..-2], mode: mode)}]"
|
29
|
+
elsif type_expression.end_with?("Type")
|
30
|
+
normalize_type_expression(type_expression[0..-5], mode: mode)
|
31
|
+
elsif type_expression.start_with?("Types::")
|
32
|
+
normalize_type_expression(type_expression[7..-1], mode: mode)
|
33
|
+
elsif type_expression.start_with?("types.")
|
34
|
+
normalize_type_expression(type_expression[6..-1], mode: mode)
|
35
|
+
else
|
36
|
+
case mode
|
37
|
+
when :ruby
|
38
|
+
case type_expression
|
39
|
+
when "Int", "Float", "Boolean", "String", "ID"
|
40
|
+
"types.#{type_expression}"
|
41
|
+
else
|
42
|
+
"Types::#{type_expression}Type"
|
43
|
+
end
|
44
|
+
when :graphql
|
45
|
+
type_expression
|
46
|
+
else
|
47
|
+
raise "Unexpected normalize mode: #{mode}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# @return [String] The user-provided type name, normalized to Ruby code
|
55
|
+
def type_ruby_name
|
56
|
+
@type_ruby_name ||= self.class.normalize_type_expression(type_name, mode: :ruby)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [String] The user-provided type name, as a GraphQL name
|
60
|
+
def type_graphql_name
|
61
|
+
@type_graphql_name ||= self.class.normalize_type_expression(type_name, mode: :graphql)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [String] The user-provided type name, as a file name (without extension)
|
65
|
+
def type_file_name
|
66
|
+
@type_file_name ||= "#{type_graphql_name}Type".underscore
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Array<Array(String, String)>>] User-provided fields, in `(name, Ruby type name)` pairs
|
70
|
+
def normalized_fields
|
71
|
+
@normalized_fields ||= fields.map { |f|
|
72
|
+
name, raw_type = f.split(":", 2)
|
73
|
+
[name, self.class.normalize_type_expression(raw_type, mode: :ruby)]
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|