graphql_backed 0.1.0 → 0.1.1
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/graphql_backed/json_schema.rb +52 -3
- data/lib/graphql_backed/mcp.rb +1 -1
- data/lib/graphql_backed/rest.rb +1 -1
- data/lib/graphql_backed/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a21db7d71dddd530cc70c7bfb5150ccb37a53a46e2bab3b91c7c50f366dff30c
|
|
4
|
+
data.tar.gz: 53fa12435b06da5fc3f17409bc1f7980364df6dc739593557501dee033cde440
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35d313b0387dac02a4f50a857c79e8eb7a4d9605b62b5eadebeafc0d359eee7247ed07b836062aa0e302636a38f0bf8fae443289e42e514949d15bbe5383d6df
|
|
7
|
+
data.tar.gz: '091739d2f38b081802ea87b962f9e5798911c539fd65744fc07dc4e1ae925570468980801a8c4509ec7f0a1ac052c4ce2eebfe448eaaca2cd3dfe2c4ca5c04f8'
|
|
@@ -33,6 +33,10 @@ module GraphQLBacked
|
|
|
33
33
|
#
|
|
34
34
|
# Each variable is described by the first argument that it's passed to, if that argument has a description.
|
|
35
35
|
#
|
|
36
|
+
# Default values are included as `"default"`: a variable's own default, or else the default of the argument
|
|
37
|
+
# that it's passed to (if it's passed to several, only when they all have the same default). Input objects' arguments
|
|
38
|
+
# have their defaults too. `null` defaults are left out.
|
|
39
|
+
#
|
|
36
40
|
# `scalars` are schemas for custom scalars, by name. See Service.scalar_json_schema.
|
|
37
41
|
#
|
|
38
42
|
#: (singleton(GraphQL::Schema) schema, singleton(Operation) operation_class, ?scalars: Hash[String, Hash[String, untyped]]) -> Hash[String, untyped]
|
|
@@ -47,6 +51,7 @@ module GraphQLBacked
|
|
|
47
51
|
@operation_class = operation_class
|
|
48
52
|
@scalars = scalars
|
|
49
53
|
@defs = {} #: Hash[String, untyped]
|
|
54
|
+
@variable_arguments = {} #: Hash[String, Array[untyped]]
|
|
50
55
|
end
|
|
51
56
|
|
|
52
57
|
#: -> Hash[String, untyped]
|
|
@@ -56,7 +61,8 @@ module GraphQLBacked
|
|
|
56
61
|
required = [] #: Array[String]
|
|
57
62
|
@operation_class.definition.variables.each do |variable|
|
|
58
63
|
type = @schema.type_from_ast(variable.type)
|
|
59
|
-
|
|
64
|
+
default = variable.default_value.nil? ? argument_default(variable.name) : literal_value(variable.default_value)
|
|
65
|
+
properties[variable.name] = with_default(JSONSchema.with_description(type_schema(type), descriptions[variable.name]), default)
|
|
60
66
|
required << variable.name if type.non_null? && variable.default_value.nil?
|
|
61
67
|
end
|
|
62
68
|
result = { "type" => "object", "properties" => properties } #: Hash[String, untyped]
|
|
@@ -82,7 +88,7 @@ module GraphQLBacked
|
|
|
82
88
|
required = [] #: Array[String]
|
|
83
89
|
input_object["properties"] = type.arguments.to_h do |name, argument|
|
|
84
90
|
required << name if argument.type.non_null? && !argument.default_value?
|
|
85
|
-
[name, JSONSchema.with_description(type_schema(argument.type), argument.description)]
|
|
91
|
+
[name, with_default(JSONSchema.with_description(type_schema(argument.type), argument.description), default_value(argument))]
|
|
86
92
|
end
|
|
87
93
|
input_object["required"] = required if required.any?
|
|
88
94
|
JSONSchema.with_description(input_object, type.description)
|
|
@@ -93,7 +99,49 @@ module GraphQLBacked
|
|
|
93
99
|
end
|
|
94
100
|
end
|
|
95
101
|
|
|
96
|
-
|
|
102
|
+
#: (Hash[String, untyped] json_schema, untyped default) -> Hash[String, untyped]
|
|
103
|
+
def with_default(json_schema, default)
|
|
104
|
+
json_schema["default"] = default unless default.nil?
|
|
105
|
+
json_schema
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# The default value of `argument` as it would be written in variables, if it has one
|
|
109
|
+
#
|
|
110
|
+
#: (untyped argument) -> untyped
|
|
111
|
+
def default_value(argument)
|
|
112
|
+
return nil if !argument.default_value?
|
|
113
|
+
value = argument.default_value
|
|
114
|
+
return nil if value.nil?
|
|
115
|
+
type = argument.type
|
|
116
|
+
# A single value is a valid default for a list
|
|
117
|
+
value = [value] if (type.non_null? ? type.of_type : type).list? && !value.respond_to?(:map)
|
|
118
|
+
type.coerce_isolated_result(value)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# The default that's used when the variable named `name` is omitted and has no default of its own:
|
|
122
|
+
# the one that's shared by every argument that it's passed to.
|
|
123
|
+
#
|
|
124
|
+
#: (String name) -> untyped
|
|
125
|
+
def argument_default(name)
|
|
126
|
+
defaults = @variable_arguments.fetch(name, []).map { |argument| default_value(argument) }.uniq #: Array[untyped]
|
|
127
|
+
defaults.size == 1 ? defaults.first : nil
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# The JSON value of a default written in GraphQL
|
|
131
|
+
#
|
|
132
|
+
#: (untyped node) -> untyped
|
|
133
|
+
def literal_value(node)
|
|
134
|
+
case node
|
|
135
|
+
when GraphQL::Language::Nodes::NullValue then nil
|
|
136
|
+
when GraphQL::Language::Nodes::Enum then node.name
|
|
137
|
+
when GraphQL::Language::Nodes::InputObject then node.arguments.to_h { |argument| [argument.name, literal_value(argument.value)] }
|
|
138
|
+
when Array then node.map { |item| literal_value(item) }
|
|
139
|
+
else node
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# The description of the first described argument that each variable is passed to, by variable name.
|
|
144
|
+
# This also gathers the arguments that each variable is passed to, for #argument_default.
|
|
97
145
|
#
|
|
98
146
|
#: -> Hash[String, String?]
|
|
99
147
|
def variable_descriptions
|
|
@@ -146,6 +194,7 @@ module GraphQLBacked
|
|
|
146
194
|
case value
|
|
147
195
|
when GraphQL::Language::Nodes::VariableIdentifier
|
|
148
196
|
descriptions[value.name] ||= argument.description
|
|
197
|
+
(@variable_arguments[value.name] ||= []) << argument
|
|
149
198
|
when GraphQL::Language::Nodes::InputObject
|
|
150
199
|
describe_arguments(argument.type.unwrap, value.arguments, descriptions)
|
|
151
200
|
when Array
|
data/lib/graphql_backed/mcp.rb
CHANGED
|
@@ -24,7 +24,7 @@ module GraphQLBacked
|
|
|
24
24
|
# - its name is Operation.public_name
|
|
25
25
|
# - its description is Operation.description, or else the description of its root field in the schema
|
|
26
26
|
# - its hints come from Operation.query?, Operation.destructive?, Operation.idempotent? and Operation.open_world?
|
|
27
|
-
# - its input is the operation's variables, each described by the argument that it's passed to
|
|
27
|
+
# - its input is the operation's variables, each described by the argument that it's passed to, with its default value
|
|
28
28
|
# - its output schema describes the `"data"` of the GraphQL response, based on the operation's selections,
|
|
29
29
|
# with the description of each field and each Resource as a reusable definition
|
|
30
30
|
# - custom scalars are described by Service.scalar_json_schema
|
data/lib/graphql_backed/rest.rb
CHANGED
|
@@ -109,7 +109,7 @@ module GraphQLBacked
|
|
|
109
109
|
# - variables in its path are `path` parameters
|
|
110
110
|
# - its other variables are `query` parameters for `GET` and `DELETE` operations, or else properties of the JSON request body.
|
|
111
111
|
# List parameters are named with `[]` (`ids[]=1&ids[]=2`) and input objects use the `deepObject` style (`filter[role]=ADMIN`).
|
|
112
|
-
# Each one is described by the argument that it's passed to.
|
|
112
|
+
# Each one is described by the argument that it's passed to, with its default value.
|
|
113
113
|
# - its `200` response is described by the selections of its root field, with the description of each field
|
|
114
114
|
# - input objects and Resources are shared in `components.schemas`, named after the input type or Resource.fragment_name
|
|
115
115
|
# (eg `Resources__User`). If two operations define different fragments with the same name, the second
|