diff --git a/src/config/schema.ts b/src/config/schema.ts index eec4c86..866500a 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -112,7 +112,8 @@ export const configSchema = object({ * interface functions to enforce a type contract. * * Type names can be optionally passed with the classMethods config to generate the interface with `suspend` functions or - * `java.util.concurrent.CompletableFuture` functions. + * `java.util.concurrent.CompletableFuture` functions. Pass `nullableDataFetchingEnvironment: true` to make the + * `DataFetchingEnvironment` argument nullable in each resolver function for that class. * @example * [ * { @@ -125,6 +126,10 @@ export const configSchema = object({ * { * typeName: "MyCompletableFutureResolverType", * classMethods: "COMPLETABLE_FUTURE", + * }, + * { + * typeName: "MyTypeWithNullableDataFetchingEnvironment", + * nullableDataFetchingEnvironment: true, * } * ] * @link https://opensource.expediagroup.com/graphql-kotlin-codegen/docs/recommended-usage @@ -136,6 +141,7 @@ export const configSchema = object({ classMethods: optional( union([literal("SUSPEND"), literal("COMPLETABLE_FUTURE")]), ), + nullableDataFetchingEnvironment: optional(boolean()), }), ), ), diff --git a/src/definitions/field.ts b/src/definitions/field.ts index c8e05ee..39715c5 100644 --- a/src/definitions/field.ts +++ b/src/definitions/field.ts @@ -287,8 +287,7 @@ function buildFieldArguments( const argMetadata = buildTypeMetadata(arg.type, schema, config); return `${sanitizeName(arg.name.value)}: ${argMetadata.typeName}${arg.type.kind === Kind.NON_NULL_TYPE ? "" : nullableSuffix}`; }); - const dataFetchingEnvironmentArgument = - "dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment"; + const dataFetchingEnvironmentArgument = `dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment${typeInResolverInterfacesConfig?.nullableDataFetchingEnvironment ? "? = null" : ""}`; const extraFieldArguments = [dataFetchingEnvironmentArgument]; const allFieldArguments = existingFieldArguments?.concat(extraFieldArguments); return allFieldArguments?.length diff --git a/test/unit/should_honor_resolverInterfaces_config/codegen.config.ts b/test/unit/should_honor_resolverInterfaces_config/codegen.config.ts index 52b0393..2a12eb9 100644 --- a/test/unit/should_honor_resolverInterfaces_config/codegen.config.ts +++ b/test/unit/should_honor_resolverInterfaces_config/codegen.config.ts @@ -23,5 +23,9 @@ export default { typeName: "MyIncludedInterfaceSuspend", classMethods: "SUSPEND", }, + { + typeName: "MyIncludedResolverTypeWithNullDataFetchingEnvironment", + nullableDataFetchingEnvironment: true, + }, ], } satisfies GraphQLKotlinCodegenConfig; diff --git a/test/unit/should_honor_resolverInterfaces_config/expected.kt b/test/unit/should_honor_resolverInterfaces_config/expected.kt index 9598e0b..9d0af88 100644 --- a/test/unit/should_honor_resolverInterfaces_config/expected.kt +++ b/test/unit/should_honor_resolverInterfaces_config/expected.kt @@ -63,3 +63,9 @@ interface MyIncludedInterfaceSuspend { interface MyExcludedInterface { val field: String? } + +@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.OBJECT]) +open class MyIncludedResolverTypeWithNullDataFetchingEnvironment { + open fun nullableField(dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment? = null): String? = throw NotImplementedError("MyIncludedResolverTypeWithNullDataFetchingEnvironment.nullableField must be implemented.") + open fun nonNullableField(dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment? = null): String = throw NotImplementedError("MyIncludedResolverTypeWithNullDataFetchingEnvironment.nonNullableField must be implemented.") +} diff --git a/test/unit/should_honor_resolverInterfaces_config/schema.graphql b/test/unit/should_honor_resolverInterfaces_config/schema.graphql index fcce4fd..6caddac 100644 --- a/test/unit/should_honor_resolverInterfaces_config/schema.graphql +++ b/test/unit/should_honor_resolverInterfaces_config/schema.graphql @@ -51,3 +51,8 @@ interface MyIncludedInterfaceSuspend { interface MyExcludedInterface { field: String } + +type MyIncludedResolverTypeWithNullDataFetchingEnvironment { + nullableField: String + nonNullableField: String! +}