@@ -5,13 +5,24 @@ import okio.buffer
5
5
import okio.sink
6
6
import java.io.File
7
7
8
- fun IntrospectionSchema.toSDL (file : File ) {
8
+ /* *
9
+ * Previous versions of this method used to encode defaultValues as Json elements. For an example:
10
+ * "defaultValue": [0, 1]
11
+ *
12
+ * This is wrong. The spec mandates defaultValue to be GraphQL encoded String:
13
+ * "defaultValue": "[0, 1]"
14
+ *
15
+ * For backward compatibility, use [legacyDefaultValues] = true
16
+ */
17
+ fun IntrospectionSchema.toSDL (file : File , legacyDefaultValues : Boolean ) {
9
18
file.sink().buffer().use {
10
- toSDL(it)
19
+ toSDL(it, legacyDefaultValues )
11
20
}
12
21
}
13
22
14
- fun IntrospectionSchema.toSDL (sink : BufferedSink ) {
23
+ fun IntrospectionSchema.toSDL (file : File ) = toSDL(file, true )
24
+
25
+ fun IntrospectionSchema.toSDL (sink : BufferedSink , legacyDefaultValues : Boolean ) {
15
26
val builtinsTypes = setOf (
16
27
" Int" , " Float" , " String" , " Boolean" , " ID" ,
17
28
" __Directive" , " __DirectiveLocation" , " __EnumValue" , " __Field" , " __InputValue" , " __Schema" , " __Type" , " __TypeKind"
@@ -25,9 +36,9 @@ fun IntrospectionSchema.toSDL(sink: BufferedSink) {
25
36
when (it) {
26
37
is IntrospectionSchema .Type .Scalar -> it.toSDL(sink)
27
38
is IntrospectionSchema .Type .Enum -> it.toSDL(sink)
28
- is IntrospectionSchema .Type .InputObject -> it.toSDL(sink)
29
- is IntrospectionSchema .Type .Interface -> it.toSDL(sink)
30
- is IntrospectionSchema .Type .Object -> it.toSDL(sink, allInterfaces)
39
+ is IntrospectionSchema .Type .InputObject -> it.toSDL(sink, legacyDefaultValues )
40
+ is IntrospectionSchema .Type .Interface -> it.toSDL(sink, legacyDefaultValues )
41
+ is IntrospectionSchema .Type .Object -> it.toSDL(sink, allInterfaces, legacyDefaultValues )
31
42
is IntrospectionSchema .Type .Union -> it.toSDL(sink)
32
43
}
33
44
// Add a newline as a separation
@@ -40,6 +51,8 @@ fun IntrospectionSchema.toSDL(sink: BufferedSink) {
40
51
sink.writeUtf8(" }\n " )
41
52
}
42
53
54
+ fun IntrospectionSchema.toSDL (sink : BufferedSink ) = toSDL(sink, true )
55
+
43
56
private fun BufferedSink.writeDescription (description : String? , indent : String = "") {
44
57
if (! description.isNullOrBlank()) {
45
58
writeUtf8(
@@ -86,11 +99,11 @@ private fun IntrospectionSchema.Type.Enum.Value.toSDL(sink: BufferedSink) {
86
99
sink.writeDeprecatedDirective(isDeprecated, deprecationReason)
87
100
}
88
101
89
- private fun IntrospectionSchema.Type.InputObject.toSDL (sink : BufferedSink ) {
102
+ private fun IntrospectionSchema.Type.InputObject.toSDL (sink : BufferedSink , legacyDefaultValues : Boolean ) {
90
103
sink.writeDescription(description)
91
104
sink.writeUtf8(" input $name {\n " )
92
105
inputFields.forEach {
93
- it.toSDL(sink)
106
+ it.toSDL(sink, legacyDefaultValues )
94
107
sink.writeUtf8(" \n " )
95
108
}
96
109
sink.writeUtf8(" }\n " )
@@ -132,33 +145,40 @@ private fun BufferedSink.writeValue(value: Any?) {
132
145
}
133
146
}
134
147
135
- private fun IntrospectionSchema.InputField.toSDL (sink : BufferedSink ) {
148
+ private fun IntrospectionSchema.InputField.toSDL (sink : BufferedSink , legacyDefaultValues : Boolean ) {
136
149
sink.writeDescription(description, " " )
137
150
sink.writeUtf8(" $name : ${type.asGraphQLType()} " )
138
151
if (defaultValue != null ) {
139
152
sink.writeUtf8(" = " )
140
- sink.writeValue(defaultValue)
153
+ if (! legacyDefaultValues && defaultValue is String ) {
154
+ // defaultValue is already encoded as GraphQL, we can pass it verbatim
155
+ sink.writeUtf8(defaultValue)
156
+ } else {
157
+ // legacy mode if we bump into an introspection schema that doesn't encode the default value
158
+ sink.writeValue(defaultValue)
159
+ }
160
+
141
161
}
142
162
sink.writeDeprecatedDirective(isDeprecated, deprecationReason)
143
163
}
144
164
145
- private fun IntrospectionSchema.Type.Interface.toSDL (sink : BufferedSink ) {
165
+ private fun IntrospectionSchema.Type.Interface.toSDL (sink : BufferedSink , legacyDefaultValue : Boolean ) {
146
166
sink.writeDescription(description)
147
167
sink.writeUtf8(" interface $name {\n " )
148
168
fields?.forEach {
149
- it.toSDL(sink)
169
+ it.toSDL(sink, legacyDefaultValue )
150
170
sink.writeUtf8(" \n " )
151
171
}
152
172
sink.writeUtf8(" }\n " )
153
173
}
154
174
155
- private fun IntrospectionSchema.Field.toSDL (sink : BufferedSink ) {
175
+ private fun IntrospectionSchema.Field.toSDL (sink : BufferedSink , legacyDefaultValue : Boolean ) {
156
176
sink.writeDescription(description, " " )
157
177
sink.writeUtf8(" $name " )
158
178
if (args.isNotEmpty()) {
159
179
sink.writeUtf8(" (" )
160
180
args.forEachIndexed { index, arg ->
161
- arg.toSDL(sink)
181
+ arg.toSDL(sink, legacyDefaultValue )
162
182
if (index != args.size - 1 ) {
163
183
sink.writeUtf8(" , " )
164
184
}
@@ -169,20 +189,26 @@ private fun IntrospectionSchema.Field.toSDL(sink: BufferedSink) {
169
189
sink.writeDeprecatedDirective(isDeprecated, deprecationReason)
170
190
}
171
191
172
- private fun IntrospectionSchema.Field.Argument.toSDL (sink : BufferedSink ) {
192
+ private fun IntrospectionSchema.Field.Argument.toSDL (sink : BufferedSink , legacyDefaultValue : Boolean ) {
173
193
if (! description.isNullOrBlank()) {
174
194
// Write the description inline
175
195
sink.writeUtf8(" \"\"\" $description \"\"\" " )
176
196
}
177
197
sink.writeUtf8(" $name : ${type.asGraphQLType()} " )
178
198
if (defaultValue != null ) {
179
199
sink.writeUtf8(" = " )
180
- sink.writeValue(defaultValue)
200
+ if (! legacyDefaultValue && defaultValue is String ) {
201
+ // defaultValue is already encoded as GraphQL, we can pass it verbatim
202
+ sink.writeUtf8(defaultValue)
203
+ } else {
204
+ // legacy mode if we bump into an introspection schema that doesn't encode the default value
205
+ sink.writeValue(defaultValue)
206
+ }
181
207
}
182
208
sink.writeDeprecatedDirective(isDeprecated, deprecationReason)
183
209
}
184
210
185
- private fun IntrospectionSchema.Type.Object.toSDL (sink : BufferedSink , interfaces : List <IntrospectionSchema .Type .Interface >) {
211
+ private fun IntrospectionSchema.Type.Object.toSDL (sink : BufferedSink , interfaces : List <IntrospectionSchema .Type .Interface >, legacyDefaultValue : Boolean ) {
186
212
sink.writeDescription(description, " " )
187
213
sink.writeUtf8(" type $name " )
188
214
val implements = interfaces.filter {
@@ -203,7 +229,7 @@ private fun IntrospectionSchema.Type.Object.toSDL(sink: BufferedSink, interfaces
203
229
sink.writeUtf8(" {\n " )
204
230
205
231
fields?.forEach {
206
- it.toSDL(sink)
232
+ it.toSDL(sink, legacyDefaultValue )
207
233
sink.writeUtf8(" \n " )
208
234
}
209
235
0 commit comments