diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.expected similarity index 97% rename from compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum.expected rename to compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.expected index 97ab0b9a76d6a..083d930477691 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum.expected +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.expected @@ -44,7 +44,7 @@ enum Status { ==================================== OUTPUT =================================== //- __generated__/SomeComponentFragment.graphql.js /** - * SignedSource<<5f1eb0560c62a91c8a4ca0dbf2963b85>> + * SignedSource<> * @flow * @lightSyntaxTransform * @nogrep @@ -57,7 +57,7 @@ enum Status { /*:: import type { Fragment, ReaderFragment } from 'relay-runtime'; import type { User____relay_model_instance$data } from "User____relay_model_instance.graphql"; -export type Status = "ADMIN" | "USER" | "%future added value"; +export type Status = "ADMIN" | "USER"; import type { FragmentType } from "relay-runtime"; import {status as userStatusResolverType} from "UserTypeResolvers"; // Type assertion validating that `userStatusResolverType` resolver is correctly implemented. diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.input similarity index 100% rename from compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum.input rename to compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.input diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum_with_enum_suffix.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum_with_enum_suffix.expected index 619bb695dc1d2..91b6481bfe0dc 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum_with_enum_suffix.expected +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_enum_with_enum_suffix.expected @@ -45,7 +45,7 @@ enum Status { ==================================== OUTPUT =================================== //- __generated__/SomeComponentFragment.graphql.js /** - * SignedSource<<19d9d78bd05aabfe1298f8b3a0c3ae01>> + * SignedSource<> * @flow * @lightSyntaxTransform * @nogrep @@ -58,7 +58,7 @@ enum Status { /*:: import type { Fragment, ReaderFragment } from 'relay-runtime'; import type { User____relay_model_instance$data } from "User____relay_model_instance.graphql"; -import type { Status } from "Status.LOL_WHAT"; +export type Status = "ADMIN" | "USER"; import type { FragmentType } from "relay-runtime"; import {status as userStatusResolverType} from "UserTypeResolvers"; // Type assertion validating that `userStatusResolverType` resolver is correctly implemented. diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs b/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs index 9969b29107dd0..b0f6a7e55b890 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<276e2284c38de688261ae6c3a87e49ee>> */ mod relay_compiler_integration; @@ -139,10 +139,10 @@ async fn resolver_on_interface_returns_custom_scalar() { } #[tokio::test] -async fn resolver_returns_enum() { - let input = include_str!("relay_compiler_integration/fixtures/resolver_returns_enum.input"); - let expected = include_str!("relay_compiler_integration/fixtures/resolver_returns_enum.expected"); - test_fixture(transform_fixture, file!(), "resolver_returns_enum.input", "relay_compiler_integration/fixtures/resolver_returns_enum.expected", input, expected).await; +async fn resolver_returns_client_schema_extension_enum() { + let input = include_str!("relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.input"); + let expected = include_str!("relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.expected"); + test_fixture(transform_fixture, file!(), "resolver_returns_client_schema_extension_enum.input", "relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.expected", input, expected).await; } #[tokio::test] diff --git a/compiler/crates/relay-typegen/src/write.rs b/compiler/crates/relay-typegen/src/write.rs index dfb1fe1525d1c..c7f847b3b9345 100644 --- a/compiler/crates/relay-typegen/src/write.rs +++ b/compiler/crates/relay-typegen/src/write.rs @@ -636,16 +636,18 @@ fn write_enum_definitions( writer: &mut Box, ) -> FmtResult { let enum_ids = encountered_enums.into_sorted_vec(typegen_context.schema); + let maybe_suffix = &typegen_context + .project_config + .typegen_config + .enum_module_suffix; for enum_id in enum_ids { let enum_type = typegen_context.schema.enum_(enum_id); - if let Some(enum_module_suffix) = &typegen_context - .project_config - .typegen_config - .enum_module_suffix - { + if !enum_type.is_extension && maybe_suffix.is_some() { + // We can't chain `if let` statements, so we need to unwrap here. + let suffix = maybe_suffix.as_ref().unwrap(); writer.write_import_type( &[enum_type.name.item.lookup()], - &format!("{}{}", enum_type.name.item, enum_module_suffix), + &format!("{}{}", enum_type.name.item, suffix), )?; } else { let mut members: Vec = enum_type @@ -654,10 +656,21 @@ fn write_enum_definitions( .map(|enum_value| AST::StringLiteral(StringLiteral(enum_value.value))) .collect(); - if !typegen_context - .project_config - .typegen_config - .no_future_proof_enums + // Users can specify a config option to disable the inclusion of + // FUTURE_ENUM_VALUE in the enum union. Additionally we want to avoid + // emitting FUTURE_ENUM_VALUE if the enum is actually defined on the + // client. For example in Client Schema Extensions or (some day) + // Relay Resolvers. + // + // In the case of a client defined enum, we don't need to enforce + // the breaking change semantics dictated by the GraphQL spec + // because new fields added to the client schema will simply result + // in fixable Flow/TypeScript errors elsewhere in the codebase. + if !(enum_type.is_extension + || typegen_context + .project_config + .typegen_config + .no_future_proof_enums) { members.push(AST::StringLiteral(StringLiteral(*FUTURE_ENUM_VALUE))); }