graphql 1.4.5 → 1.5.3
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 +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
|