diff --git a/lib/src/main/java/graphql/nadel/NadelExecutionHints.kt b/lib/src/main/java/graphql/nadel/NadelExecutionHints.kt index 4d12129b8..f1566c6d5 100644 --- a/lib/src/main/java/graphql/nadel/NadelExecutionHints.kt +++ b/lib/src/main/java/graphql/nadel/NadelExecutionHints.kt @@ -3,9 +3,11 @@ package graphql.nadel import graphql.nadel.hints.AllDocumentVariablesHint import graphql.nadel.hints.LegacyOperationNamesHint import graphql.nadel.hints.NadelDeferSupportHint +import graphql.nadel.hints.NadelDisableSharedTypesHint import graphql.nadel.hints.NadelExecuteOnEngineSchemaHint import graphql.nadel.hints.NadelHydrationExecutableSourceFields import graphql.nadel.hints.NadelHydrationFilterObjectTypesHint +import graphql.nadel.hints.NadelReachableUnderlyingServiceTypesHint import graphql.nadel.hints.NadelShadowUnderlyingTypeNameInvestigation import graphql.nadel.hints.NadelSharedTypeRenamesHint import graphql.nadel.hints.NadelShortCircuitEmptyQueryHint @@ -24,6 +26,8 @@ data class NadelExecutionHints( val hydrationFilterObjectTypes: NadelHydrationFilterObjectTypesHint, val hydrationExecutableSourceFields: NadelHydrationExecutableSourceFields, val shadowUnderlyingTypeNameInvestigation: NadelShadowUnderlyingTypeNameInvestigation, + val disableSharedTypes: NadelDisableSharedTypesHint, + val useReachableUnderlyingServiceTypes: NadelReachableUnderlyingServiceTypesHint, ) { /** * Returns a builder with the same field values as this object. @@ -47,6 +51,8 @@ data class NadelExecutionHints( private var hydrationFilterObjectTypes = NadelHydrationFilterObjectTypesHint { false } private var hydrationExecutableSourceFields = NadelHydrationExecutableSourceFields { false } private var shadowUnderlyingTypeNameInvestigation = NadelShadowUnderlyingTypeNameInvestigation { false } + private var disableSharedTypes = NadelDisableSharedTypesHint { false } + private var useReachableUnderlyingServiceTypes = NadelReachableUnderlyingServiceTypesHint { false } constructor() @@ -62,6 +68,8 @@ data class NadelExecutionHints( hydrationFilterObjectTypes = nadelExecutionHints.hydrationFilterObjectTypes hydrationExecutableSourceFields = nadelExecutionHints.hydrationExecutableSourceFields shadowUnderlyingTypeNameInvestigation = nadelExecutionHints.shadowUnderlyingTypeNameInvestigation + disableSharedTypes = nadelExecutionHints.disableSharedTypes + useReachableUnderlyingServiceTypes = nadelExecutionHints.useReachableUnderlyingServiceTypes } fun legacyOperationNames(flag: LegacyOperationNamesHint): Builder { @@ -119,6 +127,16 @@ data class NadelExecutionHints( return this } + fun disableSharedTypes(flag: NadelDisableSharedTypesHint): Builder { + disableSharedTypes = flag + return this + } + + fun useReachableUnderlyingServiceTypes(flag: NadelReachableUnderlyingServiceTypesHint): Builder { + useReachableUnderlyingServiceTypes = flag + return this + } + fun build(): NadelExecutionHints { return NadelExecutionHints( legacyOperationNames, @@ -132,6 +150,8 @@ data class NadelExecutionHints( hydrationFilterObjectTypes, hydrationExecutableSourceFields, shadowUnderlyingTypeNameInvestigation, + disableSharedTypes, + useReachableUnderlyingServiceTypes, ) } } diff --git a/lib/src/main/java/graphql/nadel/engine/transform/NadelServiceTypeFilterTransform.kt b/lib/src/main/java/graphql/nadel/engine/transform/NadelServiceTypeFilterTransform.kt index 63cba9476..8aed55d70 100644 --- a/lib/src/main/java/graphql/nadel/engine/transform/NadelServiceTypeFilterTransform.kt +++ b/lib/src/main/java/graphql/nadel/engine/transform/NadelServiceTypeFilterTransform.kt @@ -4,6 +4,7 @@ import graphql.introspection.Introspection import graphql.nadel.Service import graphql.nadel.ServiceExecutionHydrationDetails import graphql.nadel.ServiceExecutionResult +import graphql.nadel.definition.hydration.NadelHydrationConditionDefinition.Keyword.result import graphql.nadel.engine.NadelExecutionContext import graphql.nadel.engine.NadelServiceExecutionContext import graphql.nadel.engine.blueprint.IntrospectionService @@ -97,33 +98,43 @@ class NadelServiceTypeFilterTransform : NadelTransform { val underlyingTypeNamesOwnedByService = executionBlueprint.getUnderlyingTypeNamesForService(service) val shadow = executionContext.hints.shadowUnderlyingTypeNameInvestigation(executionContext) + val useReachableUnderlyingServiceTypes = executionContext.hints.useReachableUnderlyingServiceTypes(service) + val disableSharedTypes = executionContext.hints.disableSharedTypes(service) fun checkSharedTypes(objectTypeName: String): Boolean { - val result = executionContext.hints.sharedTypeRenames(service) - && executionBlueprint.getUnderlyingTypeName(objectTypeName) in underlyingTypeNamesOwnedByService - if (result && shadow) { - executionContext.hooks.reportSharedTypeDecisionImpact(executionContext, service, objectTypeName) + return if (disableSharedTypes) { + false + } else { + val result = executionContext.hints.sharedTypeRenames(service) + && executionBlueprint.getUnderlyingTypeName(objectTypeName) in underlyingTypeNamesOwnedByService + if (result && shadow) { + executionContext.hooks.reportSharedTypeDecisionImpact(executionContext, service, objectTypeName) + } + result } - return result } fun checkUnderlyingType(objectTypeName: String): Boolean { - val result = objectTypeName in underlyingTypeNamesOwnedByService - if (shadow) { - val reachableUnderlyingTypeNameCheck = - objectTypeName in executionBlueprint.getReachableUnderlyingTypeNamesForService(service) - val reducedUnderlyingTypeNameCheck = - objectTypeName in executionBlueprint.getReducedUnderlyingTypeNamesForService(service) - if (result != reachableUnderlyingTypeNameCheck) { - executionContext.hooks - .reportReachableTypeDecisionInconsistency(executionContext, service, objectTypeName) - } - if (result != reducedUnderlyingTypeNameCheck) { - executionContext.hooks - .reportReducedTypeDecisionInconsistency(executionContext, service, objectTypeName) + return if (useReachableUnderlyingServiceTypes) { + objectTypeName in executionBlueprint.getReachableUnderlyingTypeNamesForService(service) + } else { + val result = objectTypeName in underlyingTypeNamesOwnedByService + if (shadow) { + val reachableUnderlyingTypeNameCheck = + objectTypeName in executionBlueprint.getReachableUnderlyingTypeNamesForService(service) + val reducedUnderlyingTypeNameCheck = + objectTypeName in executionBlueprint.getReducedUnderlyingTypeNamesForService(service) + if (result != reachableUnderlyingTypeNameCheck) { + executionContext.hooks + .reportReachableTypeDecisionInconsistency(executionContext, service, objectTypeName) + } + if (result != reducedUnderlyingTypeNameCheck) { + executionContext.hooks + .reportReducedTypeDecisionInconsistency(executionContext, service, objectTypeName) + } } + result } - return result } // Assume for most cases there aren't foreign types so there is no point filtering to a new List diff --git a/lib/src/main/java/graphql/nadel/hints/NadelDisableSharedTypesHint.kt b/lib/src/main/java/graphql/nadel/hints/NadelDisableSharedTypesHint.kt new file mode 100644 index 000000000..5cfa3f12d --- /dev/null +++ b/lib/src/main/java/graphql/nadel/hints/NadelDisableSharedTypesHint.kt @@ -0,0 +1,7 @@ +package graphql.nadel.hints + +import graphql.nadel.Service + +fun interface NadelDisableSharedTypesHint { + operator fun invoke(service: Service): Boolean +} diff --git a/lib/src/main/java/graphql/nadel/hints/NadelReachableUnderlyingServiceTypesHint.kt b/lib/src/main/java/graphql/nadel/hints/NadelReachableUnderlyingServiceTypesHint.kt new file mode 100644 index 000000000..914c6e37b --- /dev/null +++ b/lib/src/main/java/graphql/nadel/hints/NadelReachableUnderlyingServiceTypesHint.kt @@ -0,0 +1,7 @@ +package graphql.nadel.hints + +import graphql.nadel.Service + +fun interface NadelReachableUnderlyingServiceTypesHint { + operator fun invoke(service: Service): Boolean +}