@@ -4,21 +4,21 @@ import graphql.execution.DataFetcherResult
4
4
import graphql.execution.batched.Batched
5
5
import graphql.language.ObjectValue
6
6
import graphql.language.StringValue
7
- import graphql.schema.Coercing
8
- import graphql.schema.DataFetchingEnvironment
9
- import graphql.schema.GraphQLScalarType
7
+ import graphql.schema.*
10
8
import kotlinx.coroutines.CompletableDeferred
11
9
import kotlinx.coroutines.channels.Channel
12
10
import kotlinx.coroutines.channels.ReceiveChannel
13
11
import kotlinx.coroutines.coroutineScope
14
12
import org.reactivestreams.Publisher
13
+ import java.io.InputStream
15
14
import java.util.*
16
15
import java.util.concurrent.CompletableFuture
16
+ import javax.servlet.http.Part
17
17
18
18
fun createSchema () = SchemaParser .newParser()
19
19
.schemaString(schemaDefinition)
20
- .resolvers(Query (), Mutation (), Subscription (), ItemResolver (), UnusedRootResolver (), UnusedResolver ())
21
- .scalars(customScalarUUID, customScalarMap, customScalarId)
20
+ .resolvers(Query (), Mutation (), Subscription (), ItemResolver (), UnusedRootResolver (), UnusedResolver (), EchoFilesResolver () )
21
+ .scalars(customScalarUUID, customScalarMap, customScalarId, uploadScalar )
22
22
.dictionary(" OtherItem" , OtherItemWithWrongName ::class )
23
23
.dictionary(" ThirdItem" , ThirdItem ::class )
24
24
.dictionary(" ComplexMapItem" , ComplexMapItem ::class )
@@ -31,6 +31,7 @@ val schemaDefinition = """
31
31
## Private comment!
32
32
scalar UUID
33
33
scalar customScalarMap
34
+ scalar Upload
34
35
35
36
type Query {
36
37
# Check if items list is empty
@@ -108,6 +109,7 @@ input ComplexInputTypeTwo {
108
109
109
110
type Mutation {
110
111
addItem(newItem: NewItemInput!): Item!
112
+ echoFiles(fileParts: [Upload!]!): [String!]!
111
113
}
112
114
113
115
type Subscription {
@@ -353,6 +355,10 @@ class ItemResolver : GraphQLResolver<Item> {
353
355
}
354
356
}
355
357
358
+ class EchoFilesResolver : GraphQLMutationResolver {
359
+ fun echoFiles (fileParts : List <Part >): List <String > = fileParts.map { String (it.inputStream.readBytes()) }
360
+ }
361
+
356
362
interface ItemInterface {
357
363
val name: String
358
364
val type: Type
@@ -373,6 +379,18 @@ data class ComplexNullable(val first: String, val second: String, val third: Str
373
379
data class ComplexInputType (val first : String , val second : List <List <ComplexInputTypeTwo >? >? )
374
380
data class ComplexInputTypeTwo (val first : String )
375
381
data class ItemWithGenericProperties (val keys : List <String >)
382
+ class MockPart (private val name : String , private val content : String ):Part{
383
+ override fun getSubmittedFileName (): String = name
384
+ override fun getName (): String = name
385
+ override fun write (fileName : String? ) = throw IllegalArgumentException (" Not supported" )
386
+ override fun getHeader (name : String ): String? = null
387
+ override fun getSize (): Long = content.toByteArray().size.toLong()
388
+ override fun getContentType (): String? = null
389
+ override fun getHeaders (name : String? ): Collection <String > = listOf ()
390
+ override fun getHeaderNames (): Collection <String > = listOf ()
391
+ override fun getInputStream (): InputStream = content.byteInputStream()
392
+ override fun delete () = throw IllegalArgumentException (" Not supported" )
393
+ }
376
394
377
395
val customScalarId = GraphQLScalarType .newScalar()
378
396
.name(" ID" )
@@ -427,3 +445,33 @@ val customScalarMap = GraphQLScalarType.newScalar()
427
445
override fun parseLiteral (input : Any? ): Map <String , Any > = (input as ObjectValue ).objectFields.associateBy { it.name }.mapValues { (it.value.value as StringValue ).value }
428
446
})
429
447
.build()
448
+
449
+ // Definition from https://github.com/graphql-java-kickstart/graphql-java-servlet/blob/master/src/main/java/graphql/servlet/core/ApolloScalars.java
450
+ val uploadScalar: GraphQLScalarType = GraphQLScalarType .newScalar()
451
+ .name(" Upload" )
452
+ .description(" A file part in a multipart request" )
453
+ .coercing(object : Coercing <Part ?, Void ?> {
454
+ override fun serialize (dataFetcherResult : Any ): Void ? {
455
+ throw CoercingSerializeException (" Upload is an input-only type" )
456
+ }
457
+
458
+ override fun parseValue (input : Any? ): Part ? {
459
+ return when (input) {
460
+ is Part -> {
461
+ input
462
+ }
463
+ null -> {
464
+ null
465
+ }
466
+ else -> {
467
+ throw CoercingParseValueException (" Expected type ${Part ::class .java.name} but was ${input.javaClass.name} " )
468
+ }
469
+ }
470
+ }
471
+
472
+ override fun parseLiteral (input : Any ): Part ? {
473
+ throw CoercingParseLiteralException (
474
+ " Must use variables to specify Upload values" )
475
+ }
476
+ }).build()
477
+
0 commit comments