diff --git a/CHANGELOG.md b/CHANGELOG.md index 544ff70fe8a..df158d3afcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Change Log ========== +# Next version + +* Downloading or converting a SDL schema from introspection now includes scalar definitions. This is required for clients to get a [full view of the schema](https://github.com/graphql/graphql-wg/blob/main/rfcs/FullSchemas.md). + # Version 4.1.1 _2025-01-24_ diff --git a/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt b/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt index 2d9ad2c8499..c8df0079c37 100644 --- a/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt +++ b/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt @@ -33,5 +33,6 @@ annotation class ApolloDeprecatedSince(val version: Version) { v4_0_0, v4_0_1, v4_0_2, + v4_1_2, } } diff --git a/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/Schema.kt b/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/Schema.kt index 4ac6fa42148..2855f74bd07 100644 --- a/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/Schema.kt +++ b/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/Schema.kt @@ -131,7 +131,7 @@ class Schema internal constructor( @ApolloInternal fun toMap(): Map { return mapOf( - "sdl" to GQLDocument(definitions, sourceLocation = null).toSDL(), + "sdl" to GQLDocument(definitions, sourceLocation = null).toSDL(indent = "", includeBuiltInScalarDefinitions = true), "keyFields" to keyFields.mapValues { it.value.toList().sorted() }, "foreignNames" to foreignNames, "directivesToStrip" to directivesToStrip, @@ -233,7 +233,7 @@ class Schema internal constructor( @ApolloInternal fun fromMap(map: Map): Schema { return Schema( - definitions = combineDefinitions((map["sdl"] as String).parseAsGQLDocument().getOrThrow().definitions, builtinDefinitions(), ConflictResolution.TakeLeft), + definitions = (map["sdl"] as String).parseAsGQLDocument().getOrThrow().definitions, keyFields = (map["keyFields"]!! as Map>).mapValues { it.value.toSet() }, foreignNames = map["foreignNames"]!! as Map, directivesToStrip = map["directivesToStrip"]!! as List, diff --git a/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/gqldocument.kt b/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/gqldocument.kt index 853a00a7263..d7d219fd8d7 100644 --- a/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/gqldocument.kt +++ b/libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/gqldocument.kt @@ -22,6 +22,8 @@ import okio.Buffer * Scalars: https://spec.graphql.org/draft/#sel-GAHXJHABAB_D4G * Directives: https://spec.graphql.org/draft/#sel-FAHnBPLCAACCcooU */ +@Deprecated("use toFullSchemaGQLDocument instead", ReplaceWith("toFullSchemaGQLDocument()")) +@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_1_2) fun GQLDocument.withBuiltinDefinitions(): GQLDocument { return withDefinitions(builtinDefinitions()) } @@ -201,22 +203,18 @@ private fun GQLDocument.withDefinitions(definitions: List): GQLDo * See https://spec.graphql.org/draft/#sel-GAHXJHABAB_D4G */ @ApolloExperimental -fun GQLDocument.toSDL(indent: String = " "): String { +fun GQLDocument.toSDL(indent: String = " ", includeBuiltInScalarDefinitions: Boolean = false): String { val buffer = Buffer() val writer = SDLWriter(buffer, indent) definitions.forEachIndexed { index, definition -> when { - definition is GQLScalarTypeDefinition && definition.name in GQLTypeDefinition.builtInTypes -> { + definition is GQLScalarTypeDefinition + && definition.name in GQLTypeDefinition.builtInTypes + && !includeBuiltInScalarDefinitions -> { // Always skip scalar definitions, it's a must in the spec return@forEachIndexed } - - definition is GQLTypeDefinition && definition.name in GQLTypeDefinition.builtInTypes || - definition is GQLDirectiveDefinition && definition.name in GQLDirectiveDefinition.builtInDirectives -> { - writer.write(definition) - } - else -> { writer.write(definition) } @@ -227,3 +225,8 @@ fun GQLDocument.toSDL(indent: String = " "): String { } return buffer.readUtf8() } + +@ApolloExperimental +@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_1_2) +@Deprecated("This is only kept for backward compatibility reasons. Use the overload instead.", level = DeprecationLevel.HIDDEN) +fun GQLDocument.toSDL(indent: String = " ") = toSDL(indent, false) \ No newline at end of file diff --git a/libraries/apollo-ast/src/jvmTest/kotlin/com/apollographql/apollo/graphql/ast/test/SDLWriterTest.kt b/libraries/apollo-ast/src/jvmTest/kotlin/com/apollographql/apollo/graphql/ast/test/SDLWriterTest.kt index 98b15260f52..5a8088c2240 100644 --- a/libraries/apollo-ast/src/jvmTest/kotlin/com/apollographql/apollo/graphql/ast/test/SDLWriterTest.kt +++ b/libraries/apollo-ast/src/jvmTest/kotlin/com/apollographql/apollo/graphql/ast/test/SDLWriterTest.kt @@ -1,6 +1,7 @@ package com.apollographql.apollo.graphql.ast.test import com.apollographql.apollo.ast.parseAsGQLDocument +import com.apollographql.apollo.ast.toFullSchemaGQLDocument import com.apollographql.apollo.ast.toGQLDocument import com.apollographql.apollo.ast.toSDL import com.apollographql.apollo.ast.withBuiltinDefinitions @@ -18,15 +19,6 @@ class SDLWriterTest { } } - @Test - fun typeRedefinitionInspectionIsIgnored() { - val sdlSchema = File("${CWD}/test-fixtures/sdl/type_redefinitions.graphqls") - - checkExpected(sdlSchema) { - it.parseAsGQLDocument().getOrThrow().withBuiltinDefinitions().toSDL(" ") - } - } - @Test fun introspectionSchema() { val jsonSchema = File("${CWD}/test-fixtures/sdl/introspection.json") diff --git a/libraries/apollo-ast/test-fixtures/sdl/type_redefinitions.expected b/libraries/apollo-ast/test-fixtures/sdl/type_redefinitions.expected deleted file mode 100644 index 3eb483ef630..00000000000 --- a/libraries/apollo-ast/test-fixtures/sdl/type_redefinitions.expected +++ /dev/null @@ -1,157 +0,0 @@ -type Query { - foo: Int -} - -type __Schema { - description: String - - types: [__Type!]! - - queryType: __Type! - - mutationType: __Type - - subscriptionType: __Type - - directives: [__Directive!]! -} - -type __Type { - kind: __TypeKind! - - name: String - - description: String - - fields(includeDeprecated: Boolean = false): [__Field!] - - interfaces: [__Type!] - - possibleTypes: [__Type!] - - enumValues(includeDeprecated: Boolean = false): [__EnumValue!] - - inputFields(includeDeprecated: Boolean = false): [__InputValue!] - - ofType: __Type - - specifiedByURL: String -} - -enum __TypeKind { - SCALAR - - OBJECT - - INTERFACE - - UNION - - ENUM - - INPUT_OBJECT - - LIST - - NON_NULL -} - -type __Field { - name: String! - - description: String - - args(includeDeprecated: Boolean = false): [__InputValue!]! - - type: __Type! - - isDeprecated: Boolean! - - deprecationReason: String -} - -type __InputValue { - name: String! - - description: String - - type: __Type! - - defaultValue: String - - isDeprecated: Boolean! - - deprecationReason: String -} - -type __EnumValue { - name: String! - - description: String - - isDeprecated: Boolean! - - deprecationReason: String -} - -type __Directive { - name: String! - - description: String - - locations: [__DirectiveLocation!]! - - args(includeDeprecated: Boolean = false): [__InputValue!]! - - isRepeatable: Boolean! -} - -enum __DirectiveLocation { - QUERY - - MUTATION - - SUBSCRIPTION - - FIELD - - FRAGMENT_DEFINITION - - FRAGMENT_SPREAD - - INLINE_FRAGMENT - - VARIABLE_DEFINITION - - SCHEMA - - SCALAR - - OBJECT - - FIELD_DEFINITION - - ARGUMENT_DEFINITION - - INTERFACE - - UNION - - ENUM - - ENUM_VALUE - - INPUT_OBJECT - - INPUT_FIELD_DEFINITION -} - -directive @skip (if: Boolean!) on FIELD|FRAGMENT_SPREAD|INLINE_FRAGMENT - -directive @include (if: Boolean!) on FIELD|FRAGMENT_SPREAD|INLINE_FRAGMENT - -directive @deprecated (reason: String! = "No longer supported") on FIELD_DEFINITION|ARGUMENT_DEFINITION|INPUT_FIELD_DEFINITION|ENUM_VALUE - -directive @defer (label: String, if: Boolean! = true) on FRAGMENT_SPREAD|INLINE_FRAGMENT - -directive @specifiedBy (url: String!) on SCALAR diff --git a/libraries/apollo-ast/test-fixtures/sdl/type_redefinitions.graphqls b/libraries/apollo-ast/test-fixtures/sdl/type_redefinitions.graphqls deleted file mode 100644 index a0a6a07f2c2..00000000000 --- a/libraries/apollo-ast/test-fixtures/sdl/type_redefinitions.graphqls +++ /dev/null @@ -1,4 +0,0 @@ -type Query { - foo: Int -} - diff --git a/libraries/apollo-gradle-plugin-external/src/main/kotlin/com/apollographql/apollo/gradle/internal/ApolloConvertSchemaTask.kt b/libraries/apollo-gradle-plugin-external/src/main/kotlin/com/apollographql/apollo/gradle/internal/ApolloConvertSchemaTask.kt index 42085c677a1..d852579ce50 100644 --- a/libraries/apollo-gradle-plugin-external/src/main/kotlin/com/apollographql/apollo/gradle/internal/ApolloConvertSchemaTask.kt +++ b/libraries/apollo-gradle-plugin-external/src/main/kotlin/com/apollographql/apollo/gradle/internal/ApolloConvertSchemaTask.kt @@ -5,6 +5,7 @@ import com.apollographql.apollo.ast.introspection.toIntrospectionSchema import com.apollographql.apollo.ast.introspection.writeTo import com.apollographql.apollo.ast.toFullSchemaGQLDocument import com.apollographql.apollo.ast.toGQLDocument +import com.apollographql.apollo.ast.toSDL import com.apollographql.apollo.ast.toUtf8 import org.gradle.api.DefaultTask import org.gradle.api.provider.Property @@ -46,7 +47,9 @@ abstract class ApolloConvertSchemaTask : DefaultTask() { } if (from.isIntrospection()) { - from.toIntrospectionSchema().toGQLDocument().toUtf8(to) + from.toIntrospectionSchema().toGQLDocument().toSDL(includeBuiltInScalarDefinitions = true).let { + to.writeText(it) + } } else { from.toGQLDocument().toFullSchemaGQLDocument().toIntrospectionSchema().writeTo(to) } diff --git a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo/tooling/SchemaDownloader.kt b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo/tooling/SchemaDownloader.kt index 5c9d3da7d65..3ccd62a5728 100644 --- a/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo/tooling/SchemaDownloader.kt +++ b/libraries/apollo-tooling/src/main/kotlin/com/apollographql/apollo/tooling/SchemaDownloader.kt @@ -127,7 +127,7 @@ object SchemaDownloader { if (sdlSchema == null) { check(introspectionSchema != null) // Convert from JSON to SDL - schema.writeText(introspectionSchema.toGQLDocument().toSDL(indent = " ")) + schema.writeText(introspectionSchema.toGQLDocument().toSDL(indent = " ", includeBuiltInScalarDefinitions = true)) } else { // Copy SDL verbatim schema.writeText(sdlSchema)