From 8dd8b36f852c4f090e40361cec19e080d1ef5693 Mon Sep 17 00:00:00 2001 From: Steven Barker Date: Wed, 8 Nov 2023 17:42:18 +1300 Subject: [PATCH 1/5] add when condition types to test assertions --- .../graphql/nadel/schema/NadelDirectives.kt | 106 +++++++++++++++++- .../nadel/schema/OverallSchemaGenerator.kt | 4 + .../kotlin/graphql/nadel/NadelSchemasTest.kt | 10 +- .../nadel/schema/NadelDirectivesTest.kt | 12 ++ 4 files changed, 126 insertions(+), 6 deletions(-) diff --git a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt index 1ce4a261e..e6ed41934 100644 --- a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt +++ b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt @@ -10,9 +10,12 @@ import graphql.language.BooleanValue import graphql.language.DirectiveDefinition.newDirectiveDefinition import graphql.language.EnumTypeDefinition.newEnumTypeDefinition import graphql.language.EnumValueDefinition.newEnumValueDefinition +import graphql.language.InputObjectTypeDefinition import graphql.language.InputObjectTypeDefinition.newInputObjectDefinition +import graphql.language.ObjectField import graphql.language.ObjectValue import graphql.language.StringValue +import graphql.language.TypeName import graphql.language.Value import graphql.nadel.dsl.FieldMappingDefinition import graphql.nadel.dsl.RemoteArgumentDefinition @@ -20,6 +23,7 @@ import graphql.nadel.dsl.RemoteArgumentSource import graphql.nadel.dsl.RemoteArgumentSource.SourceType import graphql.nadel.dsl.TypeMappingDefinition import graphql.nadel.dsl.UnderlyingServiceHydration +import graphql.nadel.engine.util.singleOfType import graphql.nadel.util.IntValue import graphql.nadel.util.description import graphql.nadel.util.emptyArrayValue @@ -34,13 +38,16 @@ import graphql.nadel.util.onInterface import graphql.nadel.util.onObject import graphql.nadel.util.onScalar import graphql.nadel.util.onUnion +import graphql.parser.Parser import graphql.schema.GraphQLAppliedDirective import graphql.schema.GraphQLAppliedDirectiveArgument import graphql.schema.GraphQLDirectiveContainer import graphql.schema.GraphQLEnumType import graphql.schema.GraphQLFieldDefinition import graphql.schema.GraphQLSchema +import graphql.schema.GraphQLUnionType import java.util.Locale +import java.util.Objects /** * If you update this file please add to NadelBuiltInTypes @@ -79,6 +86,91 @@ object NadelDirectives { ) .build() + // val nadelWhenConditionPredicateStartsWithDefinition = newInputObjectDefinition() + // .name("NadelWhenConditionPredicateStartsWith") + // .description("When condition predicate for startsWith") + // .inputValueDefinition( + // name = "startsWith", + // type = nonNull(GraphQLString), + // ) + // .build() + // + // val nadelWhenConditionPredicateEqualsDefinition = newInputObjectDefinition() + // .name("NadelWhenConditionPredicateEquals") + // .description("When condition predicate for equals") + // .inputValueDefinition( + // name = "equals", + // type = nonNull(ExtendedScalars.Json), + // ) + // .build() + // + // val nadelWhenConditionPredicateMatchesDefinition = newInputObjectDefinition() + // .name("NadelWhenConditionPredicateMatches") + // .description("When condition predicate for matches") + // .inputValueDefinition( + // name = "matches", + // type = nonNull(GraphQLString), + // ) + // .build() + // + // val nadelWhenConditionPredicateUnion = GraphQLUnionType.newUnionType() + // .name("NadelWhenConditionPredicateUnion") + // .description("Union of when condition predicates") + // .possibleType(nadelWhenConditionPredicateStartsWithDefinition) + // .possibleType(nadelWhenConditionPredicateEqualsDefinition) + // .possibleType(nadelWhenConditionPredicateMatchesDefinition) + // .build() + + // val nadelWhenConditionPredicateDefinition = newInputObjectDefinition() + // .name("NadelWhenConditionPredicate") + // .description("This allows you to specify a when condition to filter hydrations") + // .inputValueDefinition( + // name = "startsWith", + // type = nonNull(GraphQLString), + // ) + // .inputValueDefinition( + // name = "equals", + // type = nonNull(ExtendedScalars.Json), + // ) + // .inputValueDefinition( + // name = "matches", + // type = nonNull(GraphQLString), + // ) + // .build() + + val nadelWhenConditionPredicateDefinition = Parser.parse( + """ + input NadelWhenConditionPredicate @oneOf { + startsWith: String + equals: JSON + matches: String + } + """.trimIndent() + ).definitions.singleOfType() + + val nadelWhenConditionResultDefinition = newInputObjectDefinition() + .name("NadelWhenConditionResult") + .description("This allows you to specify a when condition to filter hydrations") + .inputValueDefinition( + name = "sourceField", + type = nonNull(GraphQLString), + ) + .inputValueDefinition( + name = "predicate", + type = nonNull(nadelWhenConditionPredicateDefinition), + ) + .build() + + val nadelWhenConditionDefinition = newInputObjectDefinition() + .name("NadelWhenCondition") + .description("This allows you to specify a when condition to filter hydrations") + .inputValueDefinition( + name = "result", + type = nonNull(nadelWhenConditionResultDefinition), + + ) + .build() + val hydratedDirectiveDefinition = newDirectiveDefinition() .name("hydrated") .onFieldDefinition() @@ -135,6 +227,13 @@ object NadelDirectives { description = "The arguments to the hydrated field", type = nonNull(list(nonNull(nadelHydrationArgumentDefinition))), ) + .inputValueDefinition( + name = "when", + description = "The arguments to the hydrated field", + type = TypeName.newTypeName() + .name(nadelWhenConditionDefinition.name) + .build() + ) .build() val dynamicServiceDirectiveDefinition = newDirectiveDefinition() @@ -482,6 +581,11 @@ object NadelDirectives { private fun resolveArgumentValue(graphQLArgument: GraphQLAppliedDirectiveArgument): T { @Suppress("UNCHECKED_CAST") // Trust caller. Can't do much - return ValuesResolver.valueToInternalValue(graphQLArgument.argumentValue, graphQLArgument.type, GraphQLContext.getDefault(), Locale.getDefault()) as T + return ValuesResolver.valueToInternalValue( + graphQLArgument.argumentValue, + graphQLArgument.type, + GraphQLContext.getDefault(), + Locale.getDefault() + ) as T } } diff --git a/lib/src/main/java/graphql/nadel/schema/OverallSchemaGenerator.kt b/lib/src/main/java/graphql/nadel/schema/OverallSchemaGenerator.kt index 29bd4be9f..c3e0b0489 100644 --- a/lib/src/main/java/graphql/nadel/schema/OverallSchemaGenerator.kt +++ b/lib/src/main/java/graphql/nadel/schema/OverallSchemaGenerator.kt @@ -72,6 +72,10 @@ internal class OverallSchemaGenerator { addIfNotPresent(overallRegistry, allDefinitions, NadelDirectives.nadelHydrationTemplateEnumDefinition) addIfNotPresent(overallRegistry, allDefinitions, NadelDirectives.hydratedFromDirectiveDefinition) addIfNotPresent(overallRegistry, allDefinitions, NadelDirectives.hydratedTemplateDirectiveDefinition) + addIfNotPresent(overallRegistry, allDefinitions, NadelDirectives.nadelWhenConditionPredicateDefinition) + addIfNotPresent(overallRegistry, allDefinitions, NadelDirectives.nadelWhenConditionDefinition) + addIfNotPresent(overallRegistry, allDefinitions, NadelDirectives.nadelWhenConditionResultDefinition) + addIfNotPresent(overallRegistry, allDefinitions, newScalarTypeDefinition() .name(ExtendedScalars.Json.name) .build()) diff --git a/lib/src/test/kotlin/graphql/nadel/NadelSchemasTest.kt b/lib/src/test/kotlin/graphql/nadel/NadelSchemasTest.kt index f853fd240..79947072b 100644 --- a/lib/src/test/kotlin/graphql/nadel/NadelSchemasTest.kt +++ b/lib/src/test/kotlin/graphql/nadel/NadelSchemasTest.kt @@ -73,7 +73,7 @@ class NadelSchemasTest : DescribeSpec({ .build() // then - assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "JSON")) + assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "JSON", "NadelWhenCondition", "NadelWhenConditionPredicate", "NadelWhenConditionResult")) val testService = schemas.services.single() assert(testService.underlyingSchema.userTypeNames == setOf("World", "Echo", "Query", "Food")) } @@ -149,7 +149,7 @@ class NadelSchemasTest : DescribeSpec({ .build() // then - assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "JSON")) + assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "JSON", "NadelWhenCondition", "NadelWhenConditionPredicate", "NadelWhenConditionResult")) val testService = schemas.services.single() assert(testService.underlyingSchema.userTypeNames == setOf("World", "Echo", "Query", "Food")) } @@ -211,7 +211,7 @@ class NadelSchemasTest : DescribeSpec({ .build() // then - assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "Issue", "JSON")) + assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "Issue", "JSON", "NadelWhenCondition", "NadelWhenConditionPredicate", "NadelWhenConditionResult")) val issueService = schemas.services.single { it.name == "issue" } assert(issueService.underlyingSchema.userTypeNames == setOf("Query", "Issue")) @@ -272,7 +272,7 @@ class NadelSchemasTest : DescribeSpec({ .build() // then - assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "Issue", "JSON")) + assert(schemas.engineSchema.userTypeNames == setOf("World", "Echo", "Query", "Issue", "JSON", "NadelWhenCondition", "NadelWhenConditionPredicate", "NadelWhenConditionResult")) } it("does not validate the schemas") { @@ -321,7 +321,7 @@ class NadelSchemasTest : DescribeSpec({ .build() // then - assert(schemas.engineSchema.userTypeNames == setOf("Query", "World", "Echo", "Issue", "JSON")) + assert(schemas.engineSchema.userTypeNames == setOf("Query", "World", "Echo", "Issue", "JSON", "NadelWhenCondition", "NadelWhenConditionPredicate", "NadelWhenConditionResult")) val testService = schemas.services.first { it.name == "test" } assert(testService.definitionRegistry.typeNames == setOf("Query", "Echo", "World")) diff --git a/lib/src/test/kotlin/graphql/nadel/schema/NadelDirectivesTest.kt b/lib/src/test/kotlin/graphql/nadel/schema/NadelDirectivesTest.kt index f057b25b7..d8913d94e 100644 --- a/lib/src/test/kotlin/graphql/nadel/schema/NadelDirectivesTest.kt +++ b/lib/src/test/kotlin/graphql/nadel/schema/NadelDirectivesTest.kt @@ -9,6 +9,9 @@ import graphql.nadel.schema.NadelDirectives.nadelHydrationArgumentDefinition import graphql.nadel.schema.NadelDirectives.nadelHydrationComplexIdentifiedBy import graphql.nadel.schema.NadelDirectives.nadelHydrationFromArgumentDefinition import graphql.nadel.schema.NadelDirectives.nadelHydrationTemplateEnumDefinition +import graphql.nadel.schema.NadelDirectives.nadelWhenConditionDefinition +import graphql.nadel.schema.NadelDirectives.nadelWhenConditionPredicateDefinition +import graphql.nadel.schema.NadelDirectives.nadelWhenConditionResultDefinition import graphql.schema.GraphQLSchema import graphql.schema.idl.MockedWiringFactory import graphql.schema.idl.RuntimeWiring @@ -30,6 +33,9 @@ class NadelDirectivesTest : DescribeSpec({ ${AstPrinter.printAst(nadelHydrationTemplateEnumDefinition)} ${AstPrinter.printAst(hydratedFromDirectiveDefinition)} ${AstPrinter.printAst(hydratedTemplateDirectiveDefinition)} + ${AstPrinter.printAst(nadelWhenConditionDefinition)} + ${AstPrinter.printAst(nadelWhenConditionPredicateDefinition)} + ${AstPrinter.printAst(nadelWhenConditionResultDefinition)} scalar JSON """ @@ -55,6 +61,12 @@ class NadelDirectivesTest : DescribeSpec({ {name: "fieldVal" value: "$source.namespace.issueId"} {name: "argVal" value: "$argument.cloudId"} ] + when: { + result: { + sourceField: "type" + predicate: { equals: "issue" } + } + } ) } """.trimIndent()) From 507589c99b28958cc572a437c0e73814e6f8dfa8 Mon Sep 17 00:00:00 2001 From: Steven Barker Date: Wed, 8 Nov 2023 17:45:13 +1300 Subject: [PATCH 2/5] removing unused directives --- .../graphql/nadel/schema/NadelDirectives.kt | 52 ------------------- 1 file changed, 52 deletions(-) diff --git a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt index e6ed41934..42ce51f81 100644 --- a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt +++ b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt @@ -86,58 +86,6 @@ object NadelDirectives { ) .build() - // val nadelWhenConditionPredicateStartsWithDefinition = newInputObjectDefinition() - // .name("NadelWhenConditionPredicateStartsWith") - // .description("When condition predicate for startsWith") - // .inputValueDefinition( - // name = "startsWith", - // type = nonNull(GraphQLString), - // ) - // .build() - // - // val nadelWhenConditionPredicateEqualsDefinition = newInputObjectDefinition() - // .name("NadelWhenConditionPredicateEquals") - // .description("When condition predicate for equals") - // .inputValueDefinition( - // name = "equals", - // type = nonNull(ExtendedScalars.Json), - // ) - // .build() - // - // val nadelWhenConditionPredicateMatchesDefinition = newInputObjectDefinition() - // .name("NadelWhenConditionPredicateMatches") - // .description("When condition predicate for matches") - // .inputValueDefinition( - // name = "matches", - // type = nonNull(GraphQLString), - // ) - // .build() - // - // val nadelWhenConditionPredicateUnion = GraphQLUnionType.newUnionType() - // .name("NadelWhenConditionPredicateUnion") - // .description("Union of when condition predicates") - // .possibleType(nadelWhenConditionPredicateStartsWithDefinition) - // .possibleType(nadelWhenConditionPredicateEqualsDefinition) - // .possibleType(nadelWhenConditionPredicateMatchesDefinition) - // .build() - - // val nadelWhenConditionPredicateDefinition = newInputObjectDefinition() - // .name("NadelWhenConditionPredicate") - // .description("This allows you to specify a when condition to filter hydrations") - // .inputValueDefinition( - // name = "startsWith", - // type = nonNull(GraphQLString), - // ) - // .inputValueDefinition( - // name = "equals", - // type = nonNull(ExtendedScalars.Json), - // ) - // .inputValueDefinition( - // name = "matches", - // type = nonNull(GraphQLString), - // ) - // .build() - val nadelWhenConditionPredicateDefinition = Parser.parse( """ input NadelWhenConditionPredicate @oneOf { From f3691d01c03021bb51db7cea7011143c8f77f84e Mon Sep 17 00:00:00 2001 From: sbarker2 <109047597+sbarker2@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:51:49 +1300 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Franklin Wang <9077461+gnawf@users.noreply.github.com> --- .../java/graphql/nadel/schema/NadelDirectives.kt | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt index 42ce51f81..99c362396 100644 --- a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt +++ b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt @@ -12,7 +12,6 @@ import graphql.language.EnumTypeDefinition.newEnumTypeDefinition import graphql.language.EnumValueDefinition.newEnumValueDefinition import graphql.language.InputObjectTypeDefinition import graphql.language.InputObjectTypeDefinition.newInputObjectDefinition -import graphql.language.ObjectField import graphql.language.ObjectValue import graphql.language.StringValue import graphql.language.TypeName @@ -45,9 +44,7 @@ import graphql.schema.GraphQLDirectiveContainer import graphql.schema.GraphQLEnumType import graphql.schema.GraphQLFieldDefinition import graphql.schema.GraphQLSchema -import graphql.schema.GraphQLUnionType import java.util.Locale -import java.util.Objects /** * If you update this file please add to NadelBuiltInTypes @@ -93,12 +90,12 @@ object NadelDirectives { equals: JSON matches: String } - """.trimIndent() + """.trimIndent(), ).definitions.singleOfType() val nadelWhenConditionResultDefinition = newInputObjectDefinition() .name("NadelWhenConditionResult") - .description("This allows you to specify a when condition to filter hydrations") + .description("Specify a condition for the hydration to activate based on the result") .inputValueDefinition( name = "sourceField", type = nonNull(GraphQLString), @@ -111,12 +108,11 @@ object NadelDirectives { val nadelWhenConditionDefinition = newInputObjectDefinition() .name("NadelWhenCondition") - .description("This allows you to specify a when condition to filter hydrations") + .description("Specify a condition for the hydration to activate") .inputValueDefinition( name = "result", type = nonNull(nadelWhenConditionResultDefinition), - - ) + ) .build() val hydratedDirectiveDefinition = newDirectiveDefinition() @@ -177,7 +173,7 @@ object NadelDirectives { ) .inputValueDefinition( name = "when", - description = "The arguments to the hydrated field", + description = "Specify a condition for the hydration to activate", type = TypeName.newTypeName() .name(nadelWhenConditionDefinition.name) .build() From 0e2a1ea2cf18028d90e9249287fffd65ae939013 Mon Sep 17 00:00:00 2001 From: Steven Barker Date: Wed, 15 Nov 2023 10:02:45 +1300 Subject: [PATCH 4/5] add parseType util function --- lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt index 99c362396..fdda822ce 100644 --- a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt +++ b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt @@ -83,7 +83,7 @@ object NadelDirectives { ) .build() - val nadelWhenConditionPredicateDefinition = Parser.parse( + val nadelWhenConditionPredicateDefinition = parseType( """ input NadelWhenConditionPredicate @oneOf { startsWith: String @@ -91,7 +91,7 @@ object NadelDirectives { matches: String } """.trimIndent(), - ).definitions.singleOfType() + ) val nadelWhenConditionResultDefinition = newInputObjectDefinition() .name("NadelWhenConditionResult") @@ -532,4 +532,8 @@ object NadelDirectives { Locale.getDefault() ) as T } + + inline fun parseType(sdl: String): InputObjectTypeDefinition { + return Parser.parse(sdl).definitions.singleOfType() + } } From 3e02abb3e03c3ed042444efb3c5aa2732d59eac6 Mon Sep 17 00:00:00 2001 From: Steven Barker Date: Mon, 20 Nov 2023 10:01:06 +1300 Subject: [PATCH 5/5] a inline parseType function to NadelDirectives --- lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt index fdda822ce..6a38a0599 100644 --- a/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt +++ b/lib/src/main/java/graphql/nadel/schema/NadelDirectives.kt @@ -14,6 +14,7 @@ import graphql.language.InputObjectTypeDefinition import graphql.language.InputObjectTypeDefinition.newInputObjectDefinition import graphql.language.ObjectValue import graphql.language.StringValue +import graphql.language.TypeDefinition import graphql.language.TypeName import graphql.language.Value import graphql.nadel.dsl.FieldMappingDefinition @@ -83,7 +84,7 @@ object NadelDirectives { ) .build() - val nadelWhenConditionPredicateDefinition = parseType( + val nadelWhenConditionPredicateDefinition = parseType( """ input NadelWhenConditionPredicate @oneOf { startsWith: String @@ -532,8 +533,7 @@ object NadelDirectives { Locale.getDefault() ) as T } - - inline fun parseType(sdl: String): InputObjectTypeDefinition { - return Parser.parse(sdl).definitions.singleOfType() + private inline fun > parseType(sdl: String): T { + return Parser.parse(sdl).definitions.singleOfType() } }